> > An example of where variable capture is needed is: > > macro println ($a) { > > return <<"EOF"; > > print $a; > > print "\n"; > > EOF > > } > > for my $b (1..100) { > > println $b; > > } > > And, if we inline the sub, the only difference will be...?
Okay, a bad example, in that it could be better done in other ways. Basically, the println macro is receiving $a='$b', not $a=$b. So when it plugs $a into the returning string, its actually plugging $b, which needs to get interpolated into the callers lexical scope. > macro mygrep ($code is macroblock, *@list) { > my @newlist = (); > for @list { > push @newlist, $_ if $code.(); > } > return @newlist; > } > @x = mygrep {/\S/} $fh.getlines(); > > where no code reference is ever created. It could be abused mercilessly, > but I can see the massive savings in performance that we would reap, > especially when translating/compiling this code for native or JIT > execution. This is because we don't have to fire a function call each > time we execute the block. In this example, you're using macros for compile-time computation. There's two interpretations in the manner you given. If *@list is the list of arguments being passed to mygrep, then @list contains ('$fh.getlines()'), and this isn't doing what you want. An alternative approach might be to define it as: macro mygrep ($code is macroblock, *$list) { my $return = <<'EOF'; my @newlist = (); EOF $return .= " for ($list) {\n"; $return .= <<'EOF'; push @newlist, $_ if $code.(); } return @newlist; EOF return $return; } @x = mygrep {/\S/} $fh.getlines(); Admittedly confusing due to the combination of perl code, and perl code returning perl code. This was the whole reason for the backtick and comma operators in scheme. The above macro would take the rest of the arguments to mygrep as a string, and plug them into the 'for', so that the result would have "for ($fh.getlines())" instead of "for ('$fh.getlines()')". A better use of macros for this compiletime computation might be something like: macro mapstatic ($code, *@list) { return make_perl_list( map $code @list); } print mapstatic {$_.$_} "A".."Z"; which would print: AABBCCDDEEFF, etc Yes, this can easily be done with a regular map, but the regular map would be performed everytime the code is run, which could be bad for performance inside a tight loop. I'm still fleshing out my ideas for making macros with a perlish syntax, which I'll post in a seperate email. Mike Lambert