Changeset 7341

Show
Ignore:
Timestamp:
03/01/08 21:28:42 (5 years ago)
Author:
daisuke
Message:

- Restructure modules, internal structure
- Remove singleton-ness
- Add buncha docs

Location:
lang/perl/R-Writer/trunk
Files:
5 added
1 removed
8 modified

Legend:

Unmodified
Added
Removed
  • lang/perl/R-Writer/trunk/Changes

    r7162 r7341  
    22======= 
    33 
     40.00001 Mar 01 2008 
     5  - Restructure modules, internal structure 
     6  - Remove singleton-ness 
     7  - Add buncha docs 
     8 
    490.00001_01  Feb 26 2008 
    510  - Initial release. 
  • lang/perl/R-Writer/trunk/lib/R/Writer.pm

    r7242 r7341  
    44use strict; 
    55use warnings; 
     6use 5.008; 
    67use base qw(Class::Accessor::Fast); 
    78use R::Writer::Call; 
     
    910use R::Writer::Range; 
    1011use R::Writer::Var; 
    11 use R::Writer::Util; 
    12  
    13 __PACKAGE__->mk_accessors($_) for qw(encoder); 
     12 
     13__PACKAGE__->mk_accessors($_) for qw(encoder statements); 
    1414 
    1515our $VERSION = '0.00001'; 
     
    1818}; 
    1919 
    20 my $base; 
    21  
    22 sub append { 
    23     my $self = shift; 
    24     push @{ $self->{statements} }, { code => shift }; 
    25     return $self; 
    26 } 
    27  
    28 sub R 
    29 { 
    30     my $R = R::Writer::Util::__R(); 
    31     my ($obj) = @_; 
    32  
    33     if (defined $R) { 
    34         $R->{object} = $obj if defined $obj; 
    35         return $R; 
    36     } 
    37  
    38     $base = R::Writer->new(@_) unless defined $base; 
    39     $base->{object} = $obj if defined $obj; 
    40     return $base; 
    41 } 
     20sub R { return __PACKAGE__->new(@_) } 
    4221 
    4322sub new 
     
    5332} 
    5433 
     34sub __push_statement { push @{ $_[0]->statements }, $_[1]; } 
     35 
     36# Call is a statement to call functions 
    5537sub call 
    5638{ 
    5739    my ($self, $function, @args) = @_; 
     40 
     41    # If this is the end of the call chain, then push the 
     42    # statement. Otherwise, return it 
     43    my $end_of_call_chain = ! defined wantarray; 
    5844    my $call = R::Writer::Call->new( 
    5945        call => $function, 
    6046        args => [@args], 
    61         end_of_call_chain => ! defined wantarray 
     47        end_of_call_chain => $end_of_call_chain, 
    6248    ); 
    63     push @{$self->{statements}}, $call; 
    64     return $self; 
    65 } 
    66  
    67 # XXX - This looks fishy 
     49 
     50    if ($end_of_call_chain) { 
     51        $self->__push_statement( $call ); 
     52    } 
     53    return $call; 
     54} 
     55 
     56BEGIN 
     57{ 
     58    foreach my $method qw(c expression) { 
     59        eval sprintf(<<'        EOSUB', $method, $method); 
     60            sub %s { 
     61                my $self = shift; 
     62                return R::Writer::Call->new( 
     63                    call => '%s', 
     64                    args => [ @_ ], 
     65                ); 
     66            } 
     67        EOSUB 
     68        die if $@; 
     69    } 
     70} 
     71 
     72sub var 
     73{ 
     74    my ($self, $var, $value) = @_; 
     75 
     76    my $obj = R::Writer::Var->new($var, $value, $self); 
     77    $self->__push_statement($obj); 
     78    return $obj; 
     79} 
     80 
    6881sub range 
    6982{ 
    7083    my ($self, $start, $end) = @_; 
    7184    my $obj = R::Writer::Range->new($start, $end); 
    72 #    $self->append($obj->as_string, delimiter => ""); 
    7385    $obj; 
    7486} 
    7587 
    76 sub expression 
    77 { 
    78     my ($self, $expr) = @_; 
    79     return R::Writer::Call->new( 
    80         call => 'expression', 
    81         args => [ $expr ], 
    82         end_of_call_chain => 1, 
    83     ); 
    84 } 
    85 *expr = \&expression; 
    86  
     88# Turn myself into a string 
    8789sub as_string 
    8890{ 
     
    9193 
    9294    for my $s (@{$self->{statements}}) { 
    93         if (eval { $s->isa('R::Writer::Call') }) { 
     95        my $delimiter = defined $s->{delimiter}  ? $s->{delimiter} : ";"; 
     96        if (my $c = $s->{code}) { 
     97            $ret .= $c; 
     98        } 
     99        else { 
    94100            $ret .= $s->as_string($self); 
    95101        } 
    96         elsif (my $c = $s->{code}) { 
    97             my $delimiter = defined $s->{delimiter}  ? $s->{delimiter} : ";"; 
    98             $c .= $delimiter unless $c =~ /$delimiter\s*$/s; 
    99             $ret .= $c ."\n"; 
    100         } 
     102        $ret .= $delimiter unless $ret =~ /$delimiter\s*$/s; 
     103        $ret .= "\n"; 
    101104    } 
    102105    return $ret; 
    103106} 
    104107 
    105 sub obj_as_string 
     108# Turn arbitrary objects to string 
     109sub __obj_as_string 
    106110{ 
    107111    my ($self, $obj) = @_; 
     
    110114 
    111115    if ($ref eq 'CODE') { 
    112         return $self->obj_as_string($obj->()); 
     116        return $self->__obj_as_string($obj->()); 
    113117    } 
    114118    elsif ($ref =~ /^R::Writer/) { 
     
    120124    elsif ($ref eq 'ARRAY') { 
    121125        my @ret = map { 
    122             $self->obj_as_string($_) 
     126            $self->__obj_as_string($_) 
    123127        } @$obj; 
    124128 
     
    128132        my %ret; 
    129133        while (my ($k, $v) = each %$obj) { 
    130             $ret{$k} = $self->obj_as_string($v) 
     134            $ret{$k} = $self->__obj_as_string($v) 
    131135        } 
    132136        return "{" . join (",", map { $self->encoder->encode($_) . ":" . $ret{$_} } keys %ret) . "}"; 
     
    137141} 
    138142 
    139 sub var 
    140 { 
    141     my ($self, $var, $value) = @_; 
    142  
    143     my $obj = R::Writer::Var->new($var, $value, $self); 
    144     $self->append($obj->as_string($self)); 
    145     return $self; 
    146 } 
    147  
    148143sub save 
    149144{ 
    150145    my ($self, $file) = @_; 
    151146 
    152     open(my $fh, '>', $file) or die "Failed to open $file for writing: $!"; 
    153     print $fh, $self->as_string; 
    154     close($fh); 
    155 } 
     147    my $fh; 
     148    my $close = 1; 
     149    my $ref = ref $file; 
     150 
     151    if ($ref && ( $ref eq 'GLOB' || eval { $file->can('print') } )) { 
     152        $close = 0; 
     153        $fh = $file; 
     154    } else { 
     155        open($fh, '>', $file) or die "Failed to open $file for writing: $!"; 
     156    } 
     157    print $fh $self->as_string; 
     158    close($fh) if $close; 
     159} 
     160 
     161sub reset { shift->statements([]) } 
    156162 
    1571631; 
     
    172178    # cat(y); 
    173179 
    174     my $R = R(); 
    175     $R->var(x => 1) 
    176       ->var(y => 'x + 1') 
    177       ->call(cat => \'y') 
    178     ; 
     180    my $R = R::Writer->new(); 
     181    $R->var(x => 1); 
     182    $R->var(y => 'x + 1'); 
     183    $R->call('cat' => $R->expr('a * x ^ 2 + 1') ); 
    179184 
    180185    print $R->as_string; 
     
    197202Tool from within Perl. 
    198203 
    199 Implementation details heavily borrow from JavaScript::Writer. Without it, 
    200 this module wouldn't have been possible (I'm not insan... smart enough to 
    201 fiddle with DB package on my own. gugod++) 
     204It is intended to be a builder tool -- for example, you have a lot of data 
     205in your database, and you want to feed it to R -- and not necessarily a 
     206"sexy" interface to build R scripts like JavaScript::Writer. 
     207 
     208Each call constitutes a statement. Unlike JavaScript::Writer (from which this 
     209module was originally based off), you should not be using call chaining to  
     210chain statement calls. 
     211 
     212=head1 EXAAMPLE 
     213 
     214=head2 DECLARING A VARIABLE 
     215 
     216If you simply want to declare a variable and set the value to a particular 
     217value, you can use the var() method: 
     218 
     219  my $value = 1; 
     220  $R->var(x => $value); 
     221 
     222This will yield to 'x <- 1;'. 
     223 
     224If you want to assign result of an arithmetic expression, you need to specify 
     225the actual string: 
     226 
     227  $R->var( y => 'x + 1' ); 
     228 
     229This will yield to 'y <- x+ 1;' 
     230 
     231You can assign the result of a function call this way: 
     232 
     233  $R->var( y => $R->call('func', 100, 100) ); 
     234 
     235Which will yield to 'y <- func(100, 100);' 
     236 
     237=head2 CALLING ARBITRARY FUNCTIONS 
     238 
     239To call functions, you can use the call() method: 
     240 
     241  $R->call( demo => 'plotmath' ); 
     242 
     243Which will yield to 'demo("plotmath");'. 
     244 
     245You can of course use call() to feed the result of a function call to a 
     246function call to a... You get the idea: 
     247 
     248  $R->call( func1 => $R->call( func2 => $R->call( func3 => 3 ) ) ); 
     249 
     250Which will yield to 'func1(func2(func3(3)));' 
     251 
     252The call() method can cover most function use cases, including oft-used 
     253functions such as c() and expr(). For convenience, the following methods 
     254are provided as shortcust to equivalent call() invocations: 
     255 
     256=head3 expression  
     257 
     258=head3 c 
     259 
     260=head2 SPECIFYING A RANGE 
     261 
     262R allows you to specify a number range. This is achieved via range() function: 
     263 
     264  $R->var(x => $R->c( $R->range(0, 9) )); 
     265 
     266Which will yield to 'x <- c(0:9);' 
    202267 
    203268=head1 METHODS 
    204269 
    205 =head2 expression | expr 
    206  
    207 The expression() method creates an mathematical expression, which can be 
    208 assigned to a variable. Expressions that are not assigned to a variable is 
    209 pretty useless, so when using expression(), you need to pass the result 
    210 to some other method that can accept it: 
    211  
    212   $R->var(y => $R->expression('a * x ^ 2 + b * x + 1')); 
    213  
    214 The above yields 
    215  
    216   y <- expression("a * x ^ 2 + b * x + 1"); 
     270=head2 new() 
     271 
     272Creates a new instance of R::Writer 
     273 
     274=head2 R() 
     275 
     276Shortcut for the constructor call. 
     277 
     278  use R::Writer qw(R); 
     279  my $R = R(); 
     280 
     281=head2 call($funcname [, $arg1, $arg2, ...]) 
     282 
     283Calls a function with specified arguments 
     284 
     285=head2 var($name [, $value]) 
     286 
     287Declares a variable. 
     288 
     289=head2 range($start, $end) 
     290 
     291Creates a range of values 
     292 
     293=head2 reset() 
     294 
     295Resets the accumulated R code, and resets R::Writer state. 
     296 
     297=head2 as_string() 
     298 
     299Returns the string representation of accumulated R statements in the given 
     300R::Writer instance.  
     301 
     302=head2 save($filename | $fh) 
     303 
     304Saves the result of calling as_string() to the specified filename, or a  
     305handle. 
    217306 
    218307=head1 TODO 
     
    220309=over 4 
    221310 
     311=item Missing Features 
     312 
     313Need way to declare functions, execute loops. 
     314Probably need way to handle datasets. 
     315 
    222316=item Remove JavaScript-ness 
    223317 
    224318JSON and what not are probably not needed. 
    225319 
    226 =item Add Proper Documentation 
    227  
    228320=item Document Way To Feed The Script To "R" 
    229321 
     
    234326Copyright (c) 2008 Daisuke Maki C<< <daisuke@endeworks.jp> >> 
    235327 
    236 Much of the code is gratuitously taken from JavaScript::Writer, 
     328A lot of the concepts and some code is based on JavaScript::Writer, 
    237329which is by Kang-min Liu C<< <gugod@gugod.org> >> 
    238330 
  • lang/perl/R-Writer/trunk/lib/R/Writer/Call.pm

    r7242 r7341  
     1# $Id$ 
     2# 
     3# Copyright (c) 2008 Daisuke Maki <daisuke@endeworks.jp> 
     4# all rights reserved. 
     5 
    16package R::Writer::Call; 
    27use strict; 
     
    1924 
    2025    my $f = $self->call; 
    21     my $delimiter = 
    22         defined($self->delimiter) ? $self->delimiter :  
    23         $self->end_of_call_chain  ? ";" : 
    24         "." 
    25     ; 
    2626    my $args = $self->args; 
    2727    return ($self->{object} ?  "$self->{object}." : "" ) . 
     
    2929            join(",", 
    3030                 map { 
    31                      $c->obj_as_string( $_ ); 
     31                     $c->__obj_as_string( $_ ); 
    3232                 } @$args 
    33              ) . ")" . $delimiter  
     33             ) . ")" 
    3434    ; 
    3535} 
    36  
    3736 
    38371; 
    3938 
    4039__END__ 
     40 
     41=head1 NAME 
     42 
     43R::Writer::Call - Function Calls 
     44 
     45=head1 SYNOPSIS 
     46 
     47  use R::Writer::Call; 
     48  # Internal use only 
     49 
     50=head1 METHODS 
     51 
     52=head2 new 
     53 
     54=head2 as_string 
     55 
     56=cut 
  • lang/perl/R-Writer/trunk/lib/R/Writer/Encoder.pm

    r7128 r7341  
    11# $Id$ 
     2# 
     3# Copyright (c) 2008 Daisuke Maki <daisuke@endeworks.jp> 
     4# All rights reserved. 
    25 
    36package R::Writer::Encoder; 
     
    1215 
    13161; 
     17 
     18__END__ 
     19 
     20=head1 NAME 
     21 
     22R::Writer::Encoder - Default Encoder 
     23 
     24=head1 SYNOPSIS 
     25 
     26  use R::Writer::Encoder; 
     27  # Internal use only 
     28 
     29=head1 METHODS 
     30 
     31=head2 new 
     32 
     33=head2 encode 
     34 
     35=cut 
  • lang/perl/R-Writer/trunk/lib/R/Writer/Range.pm

    r7121 r7341  
    11# $Id$ 
     2# 
     3# Copyright (c) 2008 DAisuke Maki <daisuke@endeworks.jp> 
     4# All rights reserved. 
    25 
    36package R::Writer::Range; 
     
    1720 
    18211; 
     22 
     23__END__ 
     24 
     25=head1 NAME 
     26 
     27R::Writer::Range - Range Of Values 
     28 
     29=head1 SYNOPSIS 
     30 
     31  use R::Writer::Range; 
     32  # Internal use only 
     33 
     34=head1 METHODS 
     35 
     36=head2 new 
     37 
     38=head2 as_string 
     39 
     40=cut 
  • lang/perl/R-Writer/trunk/lib/R/Writer/Var.pm

    r7242 r7341  
    11# $Id$ 
     2#  
     3# Copyright (c) 2008 Daisuke Maki <daisuke2endeworks.jp> 
     4# All rights reserved. 
    25 
    36package R::Writer::Var; 
     
    3538    } 
    3639    elsif ($ref eq 'CODE') { 
    37         $s = "$var <- " . $c->obj_as_string($value->()); 
     40        $s = "$var <- " . $c->__obj_as_string($value->()); 
    3841    } 
    3942    elsif ($ref =~ /^R::Writer/) { 
     
    4750    elsif ($ref eq 'SCALAR') { 
    4851        if (defined $$value) { 
    49             my $v = $self->obj_as_string($value); 
     52            my $v = $self->__obj_as_string($value); 
    5053 
    5154            $s = "var $var = $v;"; 
     
    7073 
    71741; 
     75 
     76__END__ 
     77 
     78=head1 NAME 
     79 
     80R::Writer::Var - Variables 
     81 
     82=head1 SYNOPSIS 
     83 
     84  use R::Writer::Var; 
     85  # Internal use only 
     86 
     87=head1 METHODS 
     88 
     89=head2 new 
     90 
     91=head2 as_string 
     92 
     93=cut 
  • lang/perl/R-Writer/trunk/t/02_simple.t

    r7242 r7341  
    3535    my $y = $R->var(y => 11); 
    3636    $R->call(c => \("x", "y")); 
    37     is($R->as_string, qq/x <- 11;\ny <- 11;\nc(x,y);/); 
     37    is($R->as_string, qq/x <- 11;\ny <- 11;\nc(x,y);\n/); 
    3838} 
    3939 
     
    4444 
    4545    my $R = R::Writer->new; 
    46     $R->var(x => 1) 
    47          ->var(y => 'x + 1') 
    48          ->call(cat => \'y') 
    49     ; 
    50     is( $R->as_string, qq/x <- 1;\ny <- x + 1;\ncat(y);/); 
     46    $R->var(x => 1); 
     47    $R->var(y => 'x + 1'); 
     48    $R->call(cat => \'y'); 
     49    is( $R->as_string, qq/x <- 1;\ny <- x + 1;\ncat(y);\n/); 
    5150} 
  • lang/perl/R-Writer/trunk/t/03_assign.t

    r7242 r7341  
    77} 
    88 
    9 my $R = R::Writer->new(); 
    10 $R->var(y => $R->expression('a * x ^ 2')); 
    11 is( $R->as_string(), qq|y <- expression("a * x ^ 2");\n|); 
     9{ 
     10    my $R = R::Writer->new(); 
     11    $R->var(y => $R->expression('a * x ^ 2')); 
     12    is( $R->as_string(), qq|y <- expression("a * x ^ 2");\n|); 
     13}