Changeset 7341
- Timestamp:
- 03/01/08 21:28:42 (5 years ago)
- Location:
- lang/perl/R-Writer/trunk
- Files:
-
- 5 added
- 1 removed
- 8 modified
-
Changes (modified) (1 diff)
-
lib/R/Writer.pm (modified) (13 diffs)
-
lib/R/Writer/Call.pm (modified) (3 diffs)
-
lib/R/Writer/Encoder.pm (modified) (2 diffs)
-
lib/R/Writer/Range.pm (modified) (2 diffs)
-
lib/R/Writer/Util.pm (deleted)
-
lib/R/Writer/Var.pm (modified) (4 diffs)
-
t/02_simple.t (modified) (2 diffs)
-
t/03_assign.t (modified) (1 diff)
-
t/04_function.t (added)
-
t/05_reset.t (added)
-
t/06_save.t (added)
-
t/99_pod-coverage.t (added)
-
t/99_pod.t (added)
Legend:
- Unmodified
- Added
- Removed
-
lang/perl/R-Writer/trunk/Changes
r7162 r7341 2 2 ======= 3 3 4 0.00001 Mar 01 2008 5 - Restructure modules, internal structure 6 - Remove singleton-ness 7 - Add buncha docs 8 4 9 0.00001_01 Feb 26 2008 5 10 - Initial release. -
lang/perl/R-Writer/trunk/lib/R/Writer.pm
r7242 r7341 4 4 use strict; 5 5 use warnings; 6 use 5.008; 6 7 use base qw(Class::Accessor::Fast); 7 8 use R::Writer::Call; … … 9 10 use R::Writer::Range; 10 11 use 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); 14 14 15 15 our $VERSION = '0.00001'; … … 18 18 }; 19 19 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 } 20 sub R { return __PACKAGE__->new(@_) } 42 21 43 22 sub new … … 53 32 } 54 33 34 sub __push_statement { push @{ $_[0]->statements }, $_[1]; } 35 36 # Call is a statement to call functions 55 37 sub call 56 38 { 57 39 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; 58 44 my $call = R::Writer::Call->new( 59 45 call => $function, 60 46 args => [@args], 61 end_of_call_chain => ! defined wantarray47 end_of_call_chain => $end_of_call_chain, 62 48 ); 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 56 BEGIN 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 72 sub 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 68 81 sub range 69 82 { 70 83 my ($self, $start, $end) = @_; 71 84 my $obj = R::Writer::Range->new($start, $end); 72 # $self->append($obj->as_string, delimiter => "");73 85 $obj; 74 86 } 75 87 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 87 89 sub as_string 88 90 { … … 91 93 92 94 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 { 94 100 $ret .= $s->as_string($self); 95 101 } 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"; 101 104 } 102 105 return $ret; 103 106 } 104 107 105 sub obj_as_string 108 # Turn arbitrary objects to string 109 sub __obj_as_string 106 110 { 107 111 my ($self, $obj) = @_; … … 110 114 111 115 if ($ref eq 'CODE') { 112 return $self-> obj_as_string($obj->());116 return $self->__obj_as_string($obj->()); 113 117 } 114 118 elsif ($ref =~ /^R::Writer/) { … … 120 124 elsif ($ref eq 'ARRAY') { 121 125 my @ret = map { 122 $self-> obj_as_string($_)126 $self->__obj_as_string($_) 123 127 } @$obj; 124 128 … … 128 132 my %ret; 129 133 while (my ($k, $v) = each %$obj) { 130 $ret{$k} = $self-> obj_as_string($v)134 $ret{$k} = $self->__obj_as_string($v) 131 135 } 132 136 return "{" . join (",", map { $self->encoder->encode($_) . ":" . $ret{$_} } keys %ret) . "}"; … … 137 141 } 138 142 139 sub var140 {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 148 143 sub save 149 144 { 150 145 my ($self, $file) = @_; 151 146 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 161 sub reset { shift->statements([]) } 156 162 157 163 1; … … 172 178 # cat(y); 173 179 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') ); 179 184 180 185 print $R->as_string; … … 197 202 Tool from within Perl. 198 203 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++) 204 It is intended to be a builder tool -- for example, you have a lot of data 205 in 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 208 Each call constitutes a statement. Unlike JavaScript::Writer (from which this 209 module was originally based off), you should not be using call chaining to 210 chain statement calls. 211 212 =head1 EXAAMPLE 213 214 =head2 DECLARING A VARIABLE 215 216 If you simply want to declare a variable and set the value to a particular 217 value, you can use the var() method: 218 219 my $value = 1; 220 $R->var(x => $value); 221 222 This will yield to 'x <- 1;'. 223 224 If you want to assign result of an arithmetic expression, you need to specify 225 the actual string: 226 227 $R->var( y => 'x + 1' ); 228 229 This will yield to 'y <- x+ 1;' 230 231 You can assign the result of a function call this way: 232 233 $R->var( y => $R->call('func', 100, 100) ); 234 235 Which will yield to 'y <- func(100, 100);' 236 237 =head2 CALLING ARBITRARY FUNCTIONS 238 239 To call functions, you can use the call() method: 240 241 $R->call( demo => 'plotmath' ); 242 243 Which will yield to 'demo("plotmath");'. 244 245 You can of course use call() to feed the result of a function call to a 246 function call to a... You get the idea: 247 248 $R->call( func1 => $R->call( func2 => $R->call( func3 => 3 ) ) ); 249 250 Which will yield to 'func1(func2(func3(3)));' 251 252 The call() method can cover most function use cases, including oft-used 253 functions such as c() and expr(). For convenience, the following methods 254 are provided as shortcust to equivalent call() invocations: 255 256 =head3 expression 257 258 =head3 c 259 260 =head2 SPECIFYING A RANGE 261 262 R 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 266 Which will yield to 'x <- c(0:9);' 202 267 203 268 =head1 METHODS 204 269 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 272 Creates a new instance of R::Writer 273 274 =head2 R() 275 276 Shortcut for the constructor call. 277 278 use R::Writer qw(R); 279 my $R = R(); 280 281 =head2 call($funcname [, $arg1, $arg2, ...]) 282 283 Calls a function with specified arguments 284 285 =head2 var($name [, $value]) 286 287 Declares a variable. 288 289 =head2 range($start, $end) 290 291 Creates a range of values 292 293 =head2 reset() 294 295 Resets the accumulated R code, and resets R::Writer state. 296 297 =head2 as_string() 298 299 Returns the string representation of accumulated R statements in the given 300 R::Writer instance. 301 302 =head2 save($filename | $fh) 303 304 Saves the result of calling as_string() to the specified filename, or a 305 handle. 217 306 218 307 =head1 TODO … … 220 309 =over 4 221 310 311 =item Missing Features 312 313 Need way to declare functions, execute loops. 314 Probably need way to handle datasets. 315 222 316 =item Remove JavaScript-ness 223 317 224 318 JSON and what not are probably not needed. 225 319 226 =item Add Proper Documentation227 228 320 =item Document Way To Feed The Script To "R" 229 321 … … 234 326 Copyright (c) 2008 Daisuke Maki C<< <daisuke@endeworks.jp> >> 235 327 236 Much of the code is gratuitously taken fromJavaScript::Writer,328 A lot of the concepts and some code is based on JavaScript::Writer, 237 329 which is by Kang-min Liu C<< <gugod@gugod.org> >> 238 330 -
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 1 6 package R::Writer::Call; 2 7 use strict; … … 19 24 20 25 my $f = $self->call; 21 my $delimiter =22 defined($self->delimiter) ? $self->delimiter :23 $self->end_of_call_chain ? ";" :24 "."25 ;26 26 my $args = $self->args; 27 27 return ($self->{object} ? "$self->{object}." : "" ) . … … 29 29 join(",", 30 30 map { 31 $c-> obj_as_string( $_ );31 $c->__obj_as_string( $_ ); 32 32 } @$args 33 ) . ")" . $delimiter33 ) . ")" 34 34 ; 35 35 } 36 37 36 38 37 1; 39 38 40 39 __END__ 40 41 =head1 NAME 42 43 R::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 1 1 # $Id$ 2 # 3 # Copyright (c) 2008 Daisuke Maki <daisuke@endeworks.jp> 4 # All rights reserved. 2 5 3 6 package R::Writer::Encoder; … … 12 15 13 16 1; 17 18 __END__ 19 20 =head1 NAME 21 22 R::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 1 1 # $Id$ 2 # 3 # Copyright (c) 2008 DAisuke Maki <daisuke@endeworks.jp> 4 # All rights reserved. 2 5 3 6 package R::Writer::Range; … … 17 20 18 21 1; 22 23 __END__ 24 25 =head1 NAME 26 27 R::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 1 1 # $Id$ 2 # 3 # Copyright (c) 2008 Daisuke Maki <daisuke2endeworks.jp> 4 # All rights reserved. 2 5 3 6 package R::Writer::Var; … … 35 38 } 36 39 elsif ($ref eq 'CODE') { 37 $s = "$var <- " . $c-> obj_as_string($value->());40 $s = "$var <- " . $c->__obj_as_string($value->()); 38 41 } 39 42 elsif ($ref =~ /^R::Writer/) { … … 47 50 elsif ($ref eq 'SCALAR') { 48 51 if (defined $$value) { 49 my $v = $self-> obj_as_string($value);52 my $v = $self->__obj_as_string($value); 50 53 51 54 $s = "var $var = $v;"; … … 70 73 71 74 1; 75 76 __END__ 77 78 =head1 NAME 79 80 R::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 35 35 my $y = $R->var(y => 11); 36 36 $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/); 38 38 } 39 39 … … 44 44 45 45 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/); 51 50 } -
lang/perl/R-Writer/trunk/t/03_assign.t
r7242 r7341 7 7 } 8 8 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 }
![(please configure the [header_logo] section in trac.ini)](/share/chrome/site/your_project_logo.png)