Perl6 Macros

2002-03-26 Thread Michel J Lambert

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?

2002-03-26 Thread Aaron Sherman

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?

2002-03-26 Thread Larry Wall

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

2002-03-26 Thread Michel J Lambert

> 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