Basically, one of the goals of Perl6 was to allow for you to implement any
perl construct, in perl. None of the operators were to use any special
features that could not be done by regular subroutines. And personally, I
don't see how we're going to be able to do all this lazy evaluation of
parameters (and, if/else, etc), different lexical scopes for passed
coderefs (foreach), and so on. Lisp macros provide the ability to
implement the semantics of every single one of these constructs, but
unfortunately, has the horribly monotonous syntax. And so my goal is to
provide those same semantics to Perl, with the wonderfully appropriate and
concise syntax. I'm not sure whether such a goal is achievable, however.

> Ok, ignoring the fact ${ $body } seems to be wildly non-intuitive syntax
> for a single-interpolation, I don't see the value of manipulating macros
> as string at all. We have eval for that (eval+anon subs+closures is 99%
> of what LISP macros are, and I think that's what you're modeling this
> after).

Fine, I agree that manipulating macros as strings isn't a great idea. But
it's the closest way to perform the perl equivalent to the lisp original.

> Macros could add something to Perl, but I don't see why having a macro
> return a string instead of looking and acting like a subroutine would be
> a bad thing. In fact, as I pointed out before, you can do almost all of
> the scoping stuff that you would want out of a macro in Perl with the
> existing subroutine/code ref syntax and a special property.

I disagree here. How would I define foreach as a macro (assuming the
following, simplified syntax).
foreach $each, @array, {
  print $each;
};

Since $each is being passed to the foreach macro, the macro needs to
create a lexical scoping for $each, and place the third argument as a loop
body, within the context of the scoping it just defined.

One could argue that you could do:
foreach my $each, ...
And that parameters passing variables with 'my' prefixed get lexically
scoped at the caller, and so the subroutine would be within it. But that's
not really consistent, and is actually confusing. It also begs the
question, how does $_ get scoped?

>       sub uvula($cond,$body) is macro {
>               while($cond.()) {
>                       $body.();
>               }
>       }
>       uvula cond => sub{$_ = $fh.getlines() }, body => sub{ print; };

Ugliness aside, it's only advantage is that it could inline the contents
of the macro sub, and that could be better done with simple inlined
functions, and don't require the complexity of macros. Macros are better
suited to things that *cannot* be done with functions. Stealing from "On
Lisp", macros have the following advantages (pages 107-109 to be precise):
- Transformation: they can look inside the structure of their arguments.
pow($a,$b) can be optimized if the second argument is constant. This can
be done with a macro which checks whether the second parameter to it is an
expression, or a constant, and perform the appropriate logic.
- Binding: I've already explained this one to death. "Any operator which
is to alter the lexical bindings of its arguments must be written as a
macro."
- Conditional evaluation: how would you write 'if' or 'and' using
functions?
- Multiple evaluation: this can be emulated by receiving coderefs, and
calling them multiple times. But it requires the caller format them *as* a
coderef.
- Using the calling environment: I believe Damian likes this one for
Exporter, and flexibility, and Dan doesn't for optimization reasons.
Macros give the BOBW.
- Saving function calls: A minor one, which can be emulated with inlined
functions

> If labels are lexically scoped, There's no problem here. Of course, you
> need to "promote" all labels to the beginning of the enclosing block,
> but that's compiler magic, and doesn't violate lexical scoping.

If they're lexically scoped, yes. But this doesn't solve all the problems.
For example, what if, in this macro, I pass the 'jumpto' label to another
macro I'm calling. There's no guarantee that the inner macro, when it uses
the label I passed it, will work, since it could accidentally re-scope the
macro name itself for its own purposes. Thus, the problems with variable
capture, and the reasons for gensym.

Since macros are using a function-similar syntax, and functions are
necessarily prefix-based, it means macros are unable to express curtain
Perl constructs. For example 'A if B' type syntax is difficult to
implement with macros, which requires the macro name be seen before it can
process the code as a macro. Unless macros get further perlized in some
manner in some way.

I feel like this is a two-person debate, and the volume of text is going
to alienate other contributors. So I'll shut up on this topic, and wait to
see what Larry/Damian thinks of the 'good'ness of the idea before I try
and flesh out more ideas on the implementation.

Mike Lambert



Reply via email to