Re: Topicalizers: Why does when's EXPR pay attention to topicalizer r egardless of associated variable?

2002-03-27 Thread Aaron Sherman

On Tue, 2002-03-26 at 13:19, Larry Wall wrote:
 Aaron Sherman writes:

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

That's too bad. If OUTER could only jump up one level, it's going to be
painful. For example, when you take your example, and go back to modify
the code. It may not be glaringly obvious that adding a middle loop will
cause the code to break.

We're treading dangerously close to putting TCL's upvar into Perl, which
would be a crime against God and man. However, I think you can have a
reasonable syntax for what you want. Use labels as namespaces via a
special syntax. Then, scope labels lexically (already the case?), so you
can't use this syntax to get at callers' namespaces, etc.

Here's an example syntax:

FOO: for x {
  BAR: for y {
my $foo_under FOO:= $_;
print $_, $foo_under;
  }
}

This takes visual advantage of := as the aliasing syntax while
maintaining the look of a label. Of course, that's just one syntax
possibility. The concept here is accessing lexically-scoped namespaces
via labels.

Given this, you cannot break the code by adding a middle loop, and it's
obvious exactly what was intended.

The other syntax you could use would be less generic, but would really
nail home the idea of topic to the programmer:

FOO: for x {
  BAR: for y {
my $foo_under is topicof(FOO);
print $_, $foo_under;
  }
}

I don't like this as much, but I see the benefits.

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

Ok, I'll get right on ascii_art_toke.c. I thought I'd never get a chance
to bring machine vision into the Perl core! ;-)





Re: Perl6 Macros

2002-03-27 Thread Aaron Sherman

On Tue, 2002-03-26 at 16:26, Michel J Lambert wrote:

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

Ok, I don't get it. I'm willing to concede that I'm dense, but I need to
understand how.

This looks to me like:

sub println ($a) {
print $a, \n;
}
for my $b (1..100) {
  println $b;
}

And, if we inline the sub, the only difference will be...?

Your example seems to involve no variable capture at all, in fact, just
passing parameters to a macro. See below
 
 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.

I *can* see some advantage in:

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.

But, perhaps this is too syntax-heavy. Maybe something simpler:

sub mygrep ($code is inline, *@list) {
  my newlist = ();
  for list {
push newlist, $_ if $code.();
  }
  return newlist;
}
x = mygrep {/\S/} $fh.getlines();

Now you put it in the compiler's hands to determine if a code reference
should be generated or not. Access to $_ is the only thing that is in
question here, and I don't have a good answer off the top of my head.

It would be very interesting to see how

sub mymap ($code is inline, *@list) {
  my newlist = ();
  for list {
push newlist, $code.();
  }
  return newlist;
}
x = mymap {mygrep {$_} split //, $_} $fh.getlines();

would behave. Possibly quite efficient.

 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.

I think your ideas here are good. If a general mechanism could be found
for the syntax and deemed valuable enough to add, I'd be all for it.

However, is it really macro-specific or should it be part of the
function call syntax in general?





Re: Topicalizers: Why does when's EXPR pay attention to topicaliz er r egardless of associated variable?

2002-03-27 Thread Larry Wall

Aaron Sherman writes:
: Here's an example syntax:
: 
: FOO: for x {
:   BAR: for y {
: my $foo_under FOO:= $_;
: print $_, $foo_under;
:   }
: }

I think if we have to go through contortions to get at the outer topic
by name, it's better to just name the variable on the outer loop in the
first place.  Adding - $varname to the outer loop is safe, because it
doesn't change the semantics of topicality--now that we changed the
rule so that $_ is always aliased to the topic regardless of whether
it's aliased to an explicit variable name.

Larry



Re: Topicalizers: Why does when's EXPR pay attention to topicaliz er r egardless of associated variable?

2002-03-27 Thread Eric Roode

Larry Wall writes:
  I think if we have to go through contortions to get at the outer topic
  by name, it's better to just name the variable on the outer loop in the
  first place.  Adding - $varname to the outer loop is safe, because it
  doesn't change the semantics of topicality--now that we changed the
  rule so that $_ is always aliased to the topic regardless of whether
  it's aliased to an explicit variable name.
  
  Larry

This seems to argue against OUTER::

--
Eric J. Roode[EMAIL PROTECTED]
Senior Software Engineer, Myxa Corporation

@_=unpack C*,qq;\cw22(D\coF?!%\$D\x1e=B\cyB'\cu\cy=B\; $=0; ;$=-=$=;
push (@^A,$_[$=++]+$_),$^A[$=-1]=~s+\d[^0.=^1].+$-ord e+e
foreach map{unpack 'C'x8,$_}(\getpwuid $)[0,2,5];
print pack('C*',@^A),\n;



Re: Perl6 Macros

2002-03-27 Thread Dan Sugalski

At 10:27 AM -0500 3/27/02, Aaron Sherman wrote:
I *can* see some advantage in:

 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.

Just out of curiosity, is there anything macros (in the Lisp sense) 
can do that source filters can't?
-- 
 Dan

--it's like this---
Dan Sugalski  even samurai
[EMAIL PROTECTED] have teddy bears and even
   teddy bears get drunk



Re: Topicalizers: Why does when's EXPR pay attention to topicaliz er r egardless of associated variable?

2002-03-27 Thread Larry Wall

Eric Roode writes:
: Larry Wall writes:
:   I think if we have to go through contortions to get at the outer topic
:   by name, it's better to just name the variable on the outer loop in the
:   first place.  Adding - $varname to the outer loop is safe, because it
:   doesn't change the semantics of topicality--now that we changed the
:   rule so that $_ is always aliased to the topic regardless of whether
:   it's aliased to an explicit variable name.
:   
:   Larry
: 
: This seems to argue against OUTER::

Yeah, but we need to have OUTER:: anyway if we want to support

my $foo = $OUTER::foo;

And we need that because, unlike in Perl 5, the new $foo is introduced
immediately, not at the end of the statement.  And the reason for that
is so that something like

my foo = sub { foo() }

can recognize that recursion is supposed to happen.  (We didn't have to
deal with that in Perl 5 because we didn't have lexical subroutines.)

Anyway, as I said earlier, I made $OUTER::foo ugly on purpose.  I
particularly want people to start to gnash their teeth when they type
$OUTER::OUTER::foo, because it means they're being lazy in the wrong way.

Larry



Re: Perl6 Macros

2002-03-27 Thread Larry Wall

Dan Sugalski writes:
: Just out of curiosity, is there anything macros (in the Lisp sense) 
: can do that source filters can't?

Avoid reparsing the language themselves?

Larry



Re: Perl6 Macros

2002-03-27 Thread Michel J Lambert

New syntax is 'qs', aka quote sub, which is similar to q, except that it
interpolates all of: ${..} {..} and %{..}
All subroutines which are interpolated, are interpolated as regular text,
with no bindings, so that they get lexically scoped in the code they are
returned as part of.
Then macros essentially return a string which gets interpolated at the
call site.

macro while ($cond, $body) {
  return qs{
GENLABEL:
goto ENDLABEL if( ${ $cond } );
${ $body };
goto GENLABEL;
ENDLABEL:
  }
}

$a = 10;
while {$a0}
{
  $a--;
  print $a;
}

Or maybe, if 'macro while' is defined as:
macro while ($cond as paren-sub, $body) {


while( $a 0 ) {

}

macro for qw( '(', $var, $low, $high, ')', $body ) {
  return qs{
my ${ $var } = $low;
my $end = ${ high };
GENLABEL:
goto ENDLABEL if (${ $var }  $end);
${ $body };
${ $var }++;
goto GENLABEL;
ENDLABEL;
  }
}

for ($i 1 10) {

}

or alternately, if 'macro for' is defined as:
macro for ( $var, '=', $low, 'to', $high, $body ) {


for $i = 1 to 10 {

}

The syntax isn't as powerful as scheme's despite the above extensions to
the parameter list, because scheme has such a 'simple' syntax, so there is
no real confusion about argument parameters. Another possible parameter
syntax is something that's along the lines of a grammar, so it can have a
better idea about where to start, stop, and handle errrors, for parsing
calls to macros.

The ugliness of the symbols is necessary for the more lowlevel macros that
would compile down to very simple ops, and thus make translation to the
parrot bytecode that much easier. One additional thing the above need is
that either GENLABEL and ENDLABEL need to be renamed by qs() so that
while's within while's don't have problems, or we'd need to follow
Scheme's example of gensym, which constructs unique symbols.

In theory, it might be possible to define the language in terms of macros.
Then you just write a macro parser, and you've got your (probably slow as
hell to compile) language. ;)

Anyways, I'm trying to move beyond the stage of getting others excited
about macros, and trying to propose syntax, so they aren't just wishful
thinking. I understand the above syntax probably does have ambiguities
which aren't easily resolved, but I'm trying to get the ball rolling. I'm
just hoping Larry has some wonderful macro syntax up his sleeve, waiting
to wow us all with. :)

Mike Lambert




Re: Perl6 Macros

2002-03-27 Thread Aaron Sherman

First impression: Don't go there.

Longer answer:

On Wed, 2002-03-27 at 16:29, Michel J Lambert wrote:
 New syntax is 'qs', aka quote sub, which is similar to q, except that it
 interpolates all of: ${..} {..} and %{..}
 All subroutines which are interpolated, are interpolated as regular text,
 with no bindings, so that they get lexically scoped in the code they are
 returned as part of.
 Then macros essentially return a string which gets interpolated at the
 call site.
 
 macro while ($cond, $body) {
   return qs{
 GENLABEL:
 goto ENDLABEL if( ${ $cond } );
 ${ $body };
 goto GENLABEL;
 ENDLABEL:
   }
 }

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

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.

Again, that would look like (a third syntax actually, but very similar
to what I suggested before):

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

There may be some simpler way to construct the call (this should all be
standard Perl6 syntax, I'm not trying to change anything here), but this
overly verbose invocation avoids my having to demonstrate that I'm not
sure how such things are being handled in Perl6 yet.

You just explode the code ref so that it does not construct its own
scope (actually, it does, in the same way that braces do, but not to the
extent that subroutines do... I'd have to look at the source to remember
the difference there).

 The ugliness of the symbols is necessary for the more lowlevel macros that
 would compile down to very simple ops, and thus make translation to the
 parrot bytecode that much easier. One additional thing the above need is
 that either GENLABEL and ENDLABEL need to be renamed by qs() so that
 while's within while's don't have problems, or we'd need to follow
 Scheme's example of gensym, which constructs unique symbols.

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






Re: Perl6 Macros

2002-03-27 Thread Michel J Lambert

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






Re: Perl6 Macros

2002-03-27 Thread Buddha Buck

Michel J Lambert [EMAIL PROTECTED] writes:

 
  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.

That suggested a similar example to me...

In Lisp (or, more likely, Scheme), you get constructs like:

(let ((a 'b) (c 'd) ... ) (...))

being defined as equivalent to:

((lambda (a c ...) (...)) 'b 'd ...)

and the macro system can convert the let into the evaluated lambda.

Suppose we wanted to have a Perl construct that was similar:

my $a = let ($b - 5, $c - $x) { $b + $c };

The most similar replacement for the let to the lisp case is:

my $a = (sub { my ($b, $c) = @_; return $b, $c; })(5, $x);

With the macro system (using qs() for things to be evaluated at
compile time), I could see something like:

macro let (%) 
  { (sub { my qs(keys @_[0]) = @_; return qs(@_[1]); })(qs(values @_[1]))};

I'm not sure that that would work perfectly offhand (I suspect some
syntax tweaking would be necessary) but it's the basic idea I think
you are going for.

-- 
Buddha Buck  [EMAIL PROTECTED]

I will not die an ironic death -- Scott Ian, lead singer for 
the metal band Anthrax, after bioterrorist attacks using anthrax.