> > 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

Reply via email to