Perl6 Macros
I searched the archives with Google (what, no internal search engine??), and found the thread on perl6 macros, which I did read. >From what I saw, it mostly concentrated on using macros for speed. That should be a minor argument, especially considering this is perl. :) Common Lisp macros are incredibly powerful. I remember hearing about their power, and no one being able to explain the power to me. Then I read On Lisp, which is a great book which has since been put online: http://www.paulgraham.com/onlisp.html (I'm only 100-odd pages through, and I've found it extremely enlightening.) Basically, here's the really quick overview. Lisp code is made out of lists. The entire tree of code is basically lists of lists in the appropriate places. A macro receives its arguments *as* unevaluated lists. The macro is compiled at compiletime, and then is executed at compiletime for each time that it is used in the code. The macro is essentially a transformer that transforms given code as input, to a different set of code for output, at compiletime, with the full power of lisp. The resulting code is then inlined. This gives the macro the ability to get at the calling enviornment, meaning that the one reason (or so I was told) we need the 'calling environment' for Perl6 subs could instead use macros, and allow Dan to make the internals that much faster, since he has more freedom. This is something that I'd *really* like to see in Perl 6. Instead of receiving each argument to the macro as a list-based concrete syntax tree, it would instead receive a Perl-ish version of it, whatever that means. Hashes, arrays, etc would form the internal tree of the CST/AST. This also plays into allowing Perl to generate these CST/ASTs from within Perl, but that's a different discussion. The syntax should be simple enough that the CST/ASTs can be writeable. Lisp handled this by making the language syntax hard enough that the CST is just as easy as the language. :) Other things that are useful for macros is the ` and , and ,@ operators. These essentially are quoting operators. Any instance of , inside a `() is interpolated. This sounds similar to double-quotes, but the essential difference is that double-quotes require you to escape the things you don't want interpolated, whereas the backtick `() operator requires you to escape the things you *do* want interpolated. Writing macros to return a eval-block 'object' would be the most Perlish way, imho. You'd just need a way to interpolate the results of other eval-blocks objects or or variables into an eval-block, with some form of syntax. The only problem with them is that eval blocks have the lexical scoping, while the backtick operator provides raw code which gets interpolated at the call-site, and gets its lexical scoping *there*. Finally, calling syntax. I think macros should have the same syntax as subroutines. If I find a function is too slow, I could always macro-ize it and not have to change any of the calling code. (If we allow for inlining of functions, then this particular use of macros disappears.) The big difference between macros and inline functions in Lisp is that a macro isn't a function, can't be put into a variable, referenced, called dynamically, etc...it is a compile-time only object. They each have their uses they are best-suited for. Anyways, since I don't see macros in the camel book, I figure they're not going to be explicitly covered in any of the apocalypses, so I was hoping to inspire a little discussion here. This email is more an unorganized but related group of thoughts, which I'm hoping to use to start a useful discussion on how to Perl-ify Lisp's powerful macros to make them easier to work with. I can organize it into an formal proposal or RFC if that would help. But reading the above book, or at least understanding the concepts behind them, would be helpful in any communication over this matter. Thanks, Mike Lambert
Re: Topicalizers: Why does when's EXPR pay attention to topicalizer r egardless of associated variable?
On Thu, 2002-03-21 at 12:52, Allison Randal wrote: > On Wed, Mar 20, 2002 at 09:59:35AM -0800, Larry Wall wrote: > > > > I should update y'all to my current thinking, which is that $_ is > > always identical to the current topic, even if the topic is aliased to > > some other variable. To get at an outer topic, you'd have to use the > > same mechanism we'll use for redeclared lexicals: > > > > my $foo = $OUTER::foo; > > > > for @x {# aliases $_ > > for @y -> $y { # aliases both $x and $_ > > print $OUTER::_; > > } > > } > > I rather like this compromise. It provides the desired behaviour of > "always default to the current topic" and so eliminates the confusion > between C and other defaulting constructs. It also maintains the > "$_ is default" concept, which is quite important to people, as earlier > bits of this thread demonstrated. Ok, so am I to take it that you could say: FOO: for @x { BAR: for @y { print $FOO::_; } } Or is OUTER a special-case label? Personally, I've always prefered this syntax: for @x {\ for @y { | print;<-/ } } Which is visually appealing and raises coding style arguments to a whole new level. Now on to my reasoning for adding emoticons to Perl $;-)
Re: Topicalizers: Why does when's EXPR pay attention to topicaliz er r egardless of associated variable?
Aaron Sherman writes: : On Thu, 2002-03-21 at 12:52, Allison Randal wrote: : > On Wed, Mar 20, 2002 at 09:59:35AM -0800, Larry Wall wrote: : > > : > > I should update y'all to my current thinking, which is that $_ is : > > always identical to the current topic, even if the topic is aliased to : > > some other variable. To get at an outer topic, you'd have to use the : > > same mechanism we'll use for redeclared lexicals: : > > : > > my $foo = $OUTER::foo; : > > : > > for @x { # aliases $_ : > > for @y -> $y { # aliases both $x and $_ : > > print $OUTER::_; : > > } : > > } : > : > I rather like this compromise. It provides the desired behaviour of : > "always default to the current topic" and so eliminates the confusion : > between C and other defaulting constructs. It also maintains the : > "$_ is default" concept, which is quite important to people, as earlier : > bits of this thread demonstrated. : : Ok, so am I to take it that you could say: : : FOO: for @x { : BAR: for @y { : print $FOO::_; : } : } Er, I don't think so. : Or is OUTER a special-case label? It's a special case like MY::, and somewhat ugly to discourage you from using it when you should probably be naming your loop variables. : Personally, I've always prefered this syntax: : : for @x {\ : for @y { | : print;<-/ : } : } : : Which is visually appealing and raises coding style arguments to a whole : new level. Hmm, tempting. Larry
Re: Perl6 Macros
> macro foo($a,$b) { > return( $c // $a+$b ); > } > > print foo(1,2), "\n"; > my $c=100; > print foo(1,2) "\n"; Yeah, your example provided is correct. It's called variable capture, and there's some work required by common lisp macros to ensure that unwanted variable capture does not occur. > I don't know. It doesn't seem to me like there's a benefit here that > inline functions don't get you, AND you want programmers to ever use. Am > I missing something? Well, at first glance variable capture looks really bad. And it is, where it's not intended. But used properly, it's another valuable tool in your toolkit. For example: Common lisp defines its for loops, while loops, etc using macros, for example: macro forintlist( ( $var, $bot, $top) $code ) { return <<"EOF"; for my $var (($bot)..($top)) { $code } EOF } And can be called with: forintlist( ($a, 1=>10) { print "$a\n"; }); #note, the code block passed to while does not get evaluated on the call to while, since $a shouldn't be bound here, but rather later, when it's interpolated. 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; } Personally, I'm at a loss for how macros will fit seamlessly in Perl 6. The examples above return a string, instead of real code (to make it easier to see how the interpolation works.) The code passes in a block of code, which magically gets interpolated back into a string as its original code form. Other things which the above 'forintlist' example used was the ability to send an arbitrary structure to the macro, and have it be matched against the parameter list for the macro. This allows one more flexibility in passing parameters to a macro, as they don't need to be a straight out list/array, but can be more complicatged structures, which are automagically matched. If this were in perl 6, regular array/list argument passing could be a simple case of a more complex argument/parameter passing structure. All of these things would probably be too complex to implement in Perl 6, despite their power...they'd have some semantic mismatches with what makes Perl perl. But I love lisp's power, and just hate its syntax. If I could combine a 'real languages' syntax with the expressiveness of Perl, I'd be quite the happy camper. And that's all I'm trying to do here. Thanks, Mike Lambert