Re: The Block Returns

2003-10-16 Thread Dave Mitchell
On Thu, Oct 16, 2003 at 01:46:30AM +0100, Simon Cozens wrote:
 [EMAIL PROTECTED] (Larry Wall) writes:
  But for the time being I'm tied to an IV pole
 
 We got rid of those; they're PMC poles now.
 
 Get well soon,

Ditto!

Dave.

-- 
Little fly, thy summer's play my thoughtless hand has
terminated with extreme prejudice.
(with apologies to William Blake)


Re: The Block Returns

2003-10-15 Thread Larry Wall
On Thu, Oct 02, 2003 at 01:59:26AM -0600, Luke Palmer wrote:
: So, I must ask, what does this do:
: 
: sub foo() {
: return my $self = {
: print Block;
: return $self;
: }
: }
: 
: my $block = foo;
: print Main;
: $block();
: print End;
: 
: That is, the block returns from a function that's not currently
: executing.
: 
: Will the output be: a)
: 
: Can't 'return' from closure Block

It can't in general be determined at compile time whether the dynamic
scope contains the original sub entry, so this one won't fly.  Note also that
a given return does not just return from a particular subroutine, but a
particular subroutine invocation.  When the closure is generated, the return
throws a control exception that is specific about which invocation of foo()
is to be returned from.

: b)
: 
: Main
: Block
: Can't 'return' from closure Block
: (just like (a) but runtime)

And if that particular invocation is not in the outer dynamic scope, it
fails just like any uncaught exception, so I expect this is close to
the correct answer.  The whole point of doing this with control exceptions
is so that we can say things like

sub foo() {
bar { return }
}

and know that the return is going to return from the current sub, even if 
the closure being passed to bar() is interpreted off somewhere else.  So
return is an invariant regardless of whether bar() is a built-in or not.

: c)
: 
: Main
: Block
: 
: (the block's return returns from the main program, or whatever function
: is currently executing)

To be consistent, that would return from bar() rather than foo()
in my previous example.  That would not be what we want return to do.

: d)
: 
: Main
: Block
: Main
: Block
: Main
: Block
: ...
: 
: (the block closes over the function's return continuation)
: 
: (a) and (b) both sound pretty good.  (c) is a very bad idea, as it's
: very subtle, breaks return type safety, introduces unexpected control
: flow, etc.  We'll leave those responsibilites to Cleave :-)
: 
: Maybe (d) is the way we slip in continuations without anyone noticing.
: It's the only one of these possibilites that works intuitively with, eg.
: grep.  It still seems like it might too easily introduce subtle bugs. 

If we force novices to think about continuations, we will have
destroyed Perl as we know it.  Continuations will be need to be
carefully hidden in Perl 6, and available only by explicit request.

: Is there another meaningful possibility that I didn't cover?  I've heard
: Smalltalk has something equivalent to the sub/block distinction; what
: does it do?

Dunno about Smalltalk.  But I see sub/return as a *lexically* scoped
contract to do what the user expects, even when that contract has to
be enforced by run-time chicanery like control exceptions.

By the way, sorry I haven't be more communicative lately, but I spent
most of the last two months in the hospital, where there's no email
access.  Had a benign tumor chopped out of my stomach, and there were
complications.  Full recovery is expected, any month now.  But for the
time being I'm tied to an IV pole pumping calories into my intestines
until I learn to eat again.  So please don't expect me to come to any
conferences any time soon...

Larry


RE: The Block Returns

2003-10-03 Thread Austin Hastings


 -Original Message-
 From: Luke Palmer [mailto:[EMAIL PROTECTED]
 Sent: Thursday, October 02, 2003 10:23 PM
 To: Jeff Clites
 Cc: [EMAIL PROTECTED]; [EMAIL PROTECTED]
 Subject: Re: The Block Returns
 
 
 Jeff Clites writes:
  Speaking to the practical side, I have written code that has to 
  disentangle
  itself from the failure of a complex startup sequence. I'd love to be 
  able
  to build a dynamic exit sequence. (In fact, being able to do Cblock 
  .=
  { more_stuff(); };/C is way up on my list...)
  
  I've wanted to do that sort of thing before, but it seems simpler 
  (conceptually and practically) to build up an array of cleanup 
  subs/blocks to execute in sequence, rather than to have a .= for 
  blocks. (Another reason it's handy to keep them separate is in cases in 
  which each needs to return some information--maybe a status which 
  determines whether to proceed, etc.)
 
 But this is already supported, in its most powerful form:
 
 wrap block: { call; other_stuff() }

Hmm, no.

That does a call, which presumes a return, which burns up who-knows-how-many mips. 
Given that the compiler is being forced to remember the code in case someone overloads 
the semicolon operator, or whatever, I don't think it's unreasonable to catenate the 
.source values of various blocks, and that seems a reasonable behavior for 
Cinfix:.=(Block, Block) {...}/C.

Especially since the other way turns into:

  macro atexit(Block $b) {
get_the_current_sub().eval(my block = {};)
  unless defined block;
wrap block: { call; $b(); };
  }

Which makes two calls per additional whosit.

Frankly, I think I'd rather see:

  macro atexit($code) is parsed(/{ Perl6.line* }/) {
get_the_current_sub().eval(my $block;)
  unless defined $block;
$block .= $code;
  }

  macro return($retval) {
eval($block) if defined $block;
leave Routine, $retval;
  }

But that imposes Ceval()/C pretty frequently. Better to provide some lower-level 
hackish way to agglutinate Blocks.

=Austin
  



Re: The Block Returns

2003-10-03 Thread Luke Palmer
Austin Hastings writes:
  -Original Message-
  From: Luke Palmer [mailto:[EMAIL PROTECTED]
 
  But this is already supported, in its most powerful form:
  
  wrap block: { call; other_stuff() }
 
 Hmm, no.
 
 That does a call, which presumes a return, which burns up
 who-knows-how-many mips. Given that the compiler is being forced to
 remember the code in case someone overloads the semicolon operator, or
 whatever, I don't think it's unreasonable to catenate the .source
 values of various blocks, and that seems a reasonable behavior for
 Cinfix:.=(Block, Block) {...}/C.

Oh... so that's the reason.  Well, you can give up hope on that, I'm
pretty sure.  If you want to do something like that, mess with the text
and eval yourself.

The reason is this:

my code := { 
my $x = Hello;
print $x;
}

{
my $x = World;
code ~= { print $x }
}

In any sane way of doing things, this should print HelloWorld.  That
means that your new appended block has to push the registers and load up
a new scratchpad just like any closure would.  The only thing you're
saving is a jump to the proper address, which is mostly negligible.

 Especially since the other way turns into:
 
   macro atexit(Block $b) {
 get_the_current_sub().eval(my block = {};)
   unless defined block;
 wrap block: { call; $b(); };
   }

I really haven't the slightest idea what that's supposed to mean.

Where'd block come from?  What does Code.eval(String) mean?

 Which makes two calls per additional whosit.
 
 Frankly, I think I'd rather see:
 
   macro atexit($code) is parsed(/{ Perl6.line* }/) {
 get_the_current_sub().eval(my $block;)
   unless defined $block;
 $block .= $code;
   }
 
   macro return($retval) {
 eval($block) if defined $block;
 leave Routine, $retval;
   }
 
 But that imposes Ceval()/C pretty frequently. Better to provide some lower-level 
 hackish way to agglutinate Blocks.

And you suggest that this low-level hackish way is with a common
operator, like C~.  Oh, that's brilliant.

Luke

 
 =Austin
   
 


Re: The Block Returns

2003-10-03 Thread Simon Cozens
[EMAIL PROTECTED] (Austin Hastings) writes:
 Frankly, I think I'd rather see:

Some nits:
 
   macro atexit($code) is parsed(/{ Perl6.line* }/) {

Probably just
   macro atexit($code) is parsed(/Perl6.block/) {

 $block .= $code;
  $block _= $code;

Dunno what .= would mean now . is method call. I'm sure someone will make it
mean something. :)

 eval($block) if defined $block;

I prefer $block.compile.run to eval()

-- 
The entirely inscrutable thing to me, looking back on myself, is my total want 
of all reason, will or design in the business; I had neither the resolution to 
win Adèle, the courage to do without her, the sense to consider what was at 
last to come of it all, or the grace to think how disagreeable I was making 
myself at the time to everybody about me. - John Ruskin.


Re: The Block Returns

2003-10-03 Thread Luke Palmer
Simon Cozens writes:
 [EMAIL PROTECTED] (Austin Hastings) writes:
  Frankly, I think I'd rather see:
 
 Some nits:
  
macro atexit($code) is parsed(/{ Perl6.line* }/) {
 
 Probably just
macro atexit($code) is parsed(/Perl6.block/) {
 
  $block .= $code;
   $block _= $code;
$block ~= $code;

Rather. :-)

 Dunno what .= would mean now . is method call. I'm sure someone will make it
 mean something. :)
 
  eval($block) if defined $block;
 
 I prefer $block.compile.run to eval()

It'd might have to be, too, as $block isn't a string, it's a syntax tree
(but in string context, it might just turn into a decompiled -- or saved
-- form).

Luke


Re: The Block Returns

2003-10-03 Thread Dan Sugalski
On Fri, 3 Oct 2003, Simon Cozens wrote:

 [EMAIL PROTECTED] (Austin Hastings) writes:
  eval($block) if defined $block;

 I prefer $block.compile.run to eval()

They're not quite equivalent -- I think eval's still wrapping a try/catch
around the call.

Dan


Re: The Block Returns

2003-10-03 Thread Adam D. Lopresto
On Fri, 3 Oct 2003, Simon Cozens wrote:

 Dunno what .= would mean now . is method call. I'm sure someone will make it
 mean something. :)

I've been saying for some time now that .= should mean exactly what one would expect
it to mean, method call and assign the result, for code like

$str .= lc;
$linkedlist .= next;
$structure .= clone(deep = 1);

and such things.  Really, making it mean anything else (including nothing at all)
would be counterintuitive.
-- 
Adam Lopresto
http://cec.wustl.edu/~adam/

perl -le '$_=(split q,,,`$^Xdoc -q japh`)[1]..;y/pj/PJ/;print'


Re: The Block Returns

2003-10-03 Thread Mark A. Biggar
Austin Hastings wrote:


-Original Message-
From: Luke Palmer [mailto:[EMAIL PROTECTED]
Sent: Thursday, October 02, 2003 10:23 PM
To: Jeff Clites
Cc: [EMAIL PROTECTED]; [EMAIL PROTECTED]
Subject: Re: The Block Returns
Jeff Clites writes:

Speaking to the practical side, I have written code that has to 
disentangle
itself from the failure of a complex startup sequence. I'd love to be 
able
to build a dynamic exit sequence. (In fact, being able to do Cblock 
.=
{ more_stuff(); };/C is way up on my list...)
I've wanted to do that sort of thing before, but it seems simpler 
(conceptually and practically) to build up an array of cleanup 
subs/blocks to execute in sequence, rather than to have a .= for 
blocks. (Another reason it's handy to keep them separate is in cases in 
which each needs to return some information--maybe a status which 
determines whether to proceed, etc.)
But this is already supported, in its most powerful form:

   wrap block: { call; other_stuff() }


Hmm, no.

That does a call, which presumes a return, which burns up who-knows-how-many mips. Given that the compiler is being forced to remember the code in case someone overloads the semicolon operator, or whatever, I don't think it's unreasonable to catenate the .source values of various blocks, and that seems a reasonable behavior for Cinfix:.=(Block, Block) {...}/C.

Especially since the other way turns into:

  macro atexit(Block $b) {
get_the_current_sub().eval(my block = {};)
  unless defined block;
wrap block: { call; $b(); };
  }
Which makes two calls per additional whosit.

Frankly, I think I'd rather see:

  macro atexit($code) is parsed(/{ Perl6.line* }/) {
get_the_current_sub().eval(my $block;)
  unless defined $block;
$block .= $code;
  }
  macro return($retval) {
eval($block) if defined $block;
leave Routine, $retval;
  }
But that imposes Ceval()/C pretty frequently. Better to provide some lower-level hackish way to agglutinate Blocks.


Isn't this one of the prime examples of why CPS is being use, it allows
for Tail Recursion Optimization.  With TRO all your worries about
overhead do to the wrap go away.
--
[EMAIL PROTECTED]
[EMAIL PROTECTED]


Re: The Block Returns

2003-10-03 Thread Dan Sugalski
On Thu, 2 Oct 2003, Mark A. Biggar wrote:

 Austin Hastings wrote:

  But that imposes Ceval()/C pretty frequently. Better to provide
  some lower-level hackish way to agglutinate Blocks.


 Isn't this one of the prime examples of why CPS is being use, it allows
 for Tail Recursion Optimization.  With TRO all your worries about
 overhead do to the wrap go away.

This isn't why CPS is being used under the hood. (Nothing in perl 6
propmted CPS) I wouldn't necessarily count on being able to do tail calls
here either, as they potentially alter the semantics, or at least the
introspectable environment, of the program as they make frames go away.

Dan


Re: The Block Returns

2003-10-03 Thread Piers Cawley
Dan Sugalski [EMAIL PROTECTED] writes:

 On Thu, 2 Oct 2003, Mark A. Biggar wrote:

 Austin Hastings wrote:

  But that imposes Ceval()/C pretty frequently. Better to provide
  some lower-level hackish way to agglutinate Blocks.


 Isn't this one of the prime examples of why CPS is being use, it allows
 for Tail Recursion Optimization.  With TRO all your worries about
 overhead do to the wrap go away.

 This isn't why CPS is being used under the hood. (Nothing in perl 6
 propmted CPS) I wouldn't necessarily count on being able to do tail calls
 here either, as they potentially alter the semantics, or at least the
 introspectable environment, of the program as they make frames go away.

I'm vaguely hoping that modules will be able to declare that they
don't need to access a 'strict' caller and that they'll be happy
with a return from caller that skips any tail calls. Then, if the
Perl 6 compiler sees that all modules in play have declared
themselves in this fashion it'll use optimized tail calls. However,
thinking about that I'm not entirely sure how it could be done with a
single pass compiler.


Re: The Block Returns

2003-10-03 Thread Dan Sugalski
At 11:55 PM +0100 10/3/03, Piers Cawley wrote:
Dan Sugalski [EMAIL PROTECTED] writes:

 On Thu, 2 Oct 2003, Mark A. Biggar wrote:

 Austin Hastings wrote:

  But that imposes Ceval()/C pretty frequently. Better to provide
  some lower-level hackish way to agglutinate Blocks.
 Isn't this one of the prime examples of why CPS is being use, it allows
 for Tail Recursion Optimization.  With TRO all your worries about
 overhead do to the wrap go away.
 This isn't why CPS is being used under the hood. (Nothing in perl 6
 propmted CPS) I wouldn't necessarily count on being able to do tail calls
 here either, as they potentially alter the semantics, or at least the
 introspectable environment, of the program as they make frames go away.
I'm vaguely hoping that modules will be able to declare that they
don't need to access a 'strict' caller and that they'll be happy
with a return from caller that skips any tail calls. Then, if the
Perl 6 compiler sees that all modules in play have declared
themselves in this fashion it'll use optimized tail calls. However,
thinking about that I'm not entirely sure how it could be done with a
single pass compiler.
I think it's reasonable to allow you to mark your subs as being able 
to be tail-called out of. Subs with no lexical variables should be 
safe to call out of as well, though that's a bit dodgier. OTOH, it's 
not like too many folks walk up their call chain.
--
Dan

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


Re: The Block Returns

2003-10-03 Thread Piers Cawley
Dan Sugalski [EMAIL PROTECTED] writes:

 At 11:55 PM +0100 10/3/03, Piers Cawley wrote:
Dan Sugalski [EMAIL PROTECTED] writes:

  On Thu, 2 Oct 2003, Mark A. Biggar wrote:

  Austin Hastings wrote:

   But that imposes Ceval()/C pretty frequently. Better to provide
   some lower-level hackish way to agglutinate Blocks.


  Isn't this one of the prime examples of why CPS is being use, it allows
  for Tail Recursion Optimization.  With TRO all your worries about
  overhead do to the wrap go away.

  This isn't why CPS is being used under the hood. (Nothing in perl 6
  propmted CPS) I wouldn't necessarily count on being able to do tail calls
  here either, as they potentially alter the semantics, or at least the
  introspectable environment, of the program as they make frames go away.

I'm vaguely hoping that modules will be able to declare that they
don't need to access a 'strict' caller and that they'll be happy
with a return from caller that skips any tail calls. Then, if the
Perl 6 compiler sees that all modules in play have declared
themselves in this fashion it'll use optimized tail calls. However,
thinking about that I'm not entirely sure how it could be done with a
single pass compiler.

 I think it's reasonable to allow you to mark your subs as being able
 to be tail-called out of. Subs with no lexical variables should be
 safe to call out of as well, though that's a bit dodgier. OTOH, it's
 not like too many folks walk up their call chain.

Actually, that makes a good deal more sense than my suggestion. As
for hook functions, they probably want to hide themselves from
Ccaller anyway, or hooking a single function in a call chain could
cause introspective programs to fall over.


The Block Returns

2003-10-02 Thread Luke Palmer
So, I must ask, what does this do:

sub foo() {
return my $self = {
print Block;
return $self;
}
}

my $block = foo;
print Main;
$block();
print End;

That is, the block returns from a function that's not currently
executing.

Will the output be: a)

Can't 'return' from closure Block

b)

Main
Block
Can't 'return' from closure Block

(just like (a) but runtime)
c)

Main
Block

(the block's return returns from the main program, or whatever function
is currently executing)

d)

Main
Block
Main
Block
Main
Block
...

(the block closes over the function's return continuation)

(a) and (b) both sound pretty good.  (c) is a very bad idea, as it's
very subtle, breaks return type safety, introduces unexpected control
flow, etc.  We'll leave those responsibilites to Cleave :-)

Maybe (d) is the way we slip in continuations without anyone noticing.
It's the only one of these possibilites that works intuitively with, eg.
grep.  It still seems like it might too easily introduce subtle bugs. 

Is there another meaningful possibility that I didn't cover?  I've heard
Smalltalk has something equivalent to the sub/block distinction; what
does it do?

Luke


Re: The Block Returns

2003-10-02 Thread Stefan Lidman
So, I must ask, what does this do:

sub foo() {
return my $self = {
print Block;
return $self;
}
}

my $block = foo;
#  = sub {print Block; return $self;}

A6:
One obvious difference is that the sub on closures is now optional,
since every brace-delimited block is now essentially a closure. You
can still put the sub if you like. But it is only required if the
block would otherwise be construed as a hash value; that is, if it
appears to contain a list of pairs.

print Main;
$block();
print End;

That is, the block returns from a function that's not currently
executing.

Main
Block
End

is my guess.

/Stefan


Re: The Block Returns

2003-10-02 Thread Luke Palmer
Stefan Lidman writes:
 So, I must ask, what does this do:
 
 sub foo() {
 return my $self = {
 print Block;
 return $self;
 }
 }
 
 my $block = foo;
 #  = sub {print Block; return $self;}
 
 A6:
 One obvious difference is that the sub on closures is now optional,
 since every brace-delimited block is now essentially a closure. You
 can still put the sub if you like. But it is only required if the
 block would otherwise be construed as a hash value; that is, if it
 appears to contain a list of pairs.

Um, yeah, but just a little farther down:

Although we say the sub keyword is now optional on a closure, the
return keyword only works with an explicit sub. (There are other
ways to return values from a block.)

And to clarify:

sub indexof(Selector $which, [EMAIL PROTECTED]) {
for zip(@data, 0...) - $_, $index {
when $which { return $index }
}
}

Which actually creates a closure (well, in theory at least) on line 2
for the for loop, but the return inside of it returns from indexof.
Which is actually very, very nice.

So the question is: What happens when indexof isn't on the call chain,
but that inner closure is?

Luke

 print Main;
 $block();
 print End;
 
 That is, the block returns from a function that's not currently
 executing.
 
 Main
 Block
 End
 
 is my guess.
 
 /Stefan


Re: The Block Returns

2003-10-02 Thread Dave Mitchell
On Thu, Oct 02, 2003 at 04:15:06AM -0600, Luke Palmer wrote:
 And to clarify:
 
 sub indexof(Selector $which, [EMAIL PROTECTED]) {
 for zip(@data, 0...) - $_, $index {
 when $which { return $index }
 }
 }
 
 Which actually creates a closure (well, in theory at least) on line 2
 for the for loop, but the return inside of it returns from indexof.
 Which is actually very, very nice.
 
 So the question is: What happens when indexof isn't on the call chain,
 but that inner closure is?

But how can the inner closure be called if not via indexof?

-- 
To collect all the latest movies, simply place an unprotected ftp server
on the Internet, and wait for the disk to fill


Re: The Block Returns

2003-10-02 Thread Jonathan Scott Duff

On Thu, Oct 02, 2003 at 11:39:20AM +0100, Dave Mitchell wrote:
 On Thu, Oct 02, 2003 at 04:15:06AM -0600, Luke Palmer wrote:
  So the question is: What happens when indexof isn't on the call chain,
  but that inner closure is?
 
 But how can the inner closure be called if not via indexof?

I believe that's exactly what Luke's original example was
illustrating.

On Thu, Oct 02, 2003 at 01:59:26AM -0600, Luke Palmer wrote:
 So, I must ask, what does this do:
 
 sub foo() {
 return my $self = {
 print Block;
 return $self;
 }
 }

foo() returns a closure that contains code that returns from the foo()
subroutine (the line that says return $self)  When that closure is
then called ...

 my $block = foo;
 print Main;
 $block();

... foo() is no longer executing.

 That is, the block returns from a function that's not currently
 executing.
 
 Will the output be: a)
 
 Can't 'return' from closure Block
 
 b)
 
 Main
 Block
 Can't 'return' from closure Block
 
 (just like (a) but runtime)
 c)
 
 Main
 Block
 
 (the block's return returns from the main program, or whatever function
 is currently executing)
 
 d)
 
 Main
 Block
 Main
 Block
 Main
 Block
 ...
 
 (the block closes over the function's return continuation)

I would expect (a) to happen, but (d) has some interesting
possibilities.  And wouldn't (d) be:

Main
Block
Block
Block
...

?

Actually, if your last parenthetical were true, it would be 

Main
Block
End

because though foo()'s return continuation is closed over, it only
gets executed once and then returned.  I.e., to get Block again,
you'd need to execute the return value of $block.

my $block = foo;
print Main;
$b2 = $block();
$b3 = $b2();
$b4 = $b3();# etc.
print End;

or for the infinite version:

my $block = foo;
print Main;
$block = $block() while 1;
print End;# we never get here

Or am I missing something?

-Scott
-- 
Jonathan Scott Duff
[EMAIL PROTECTED]


Re: The Block Returns

2003-10-02 Thread Mark A. Biggar
Jonathan Scott Duff wrote:

On Thu, Oct 02, 2003 at 11:39:20AM +0100, Dave Mitchell wrote:

On Thu, Oct 02, 2003 at 04:15:06AM -0600, Luke Palmer wrote:

So the question is: What happens when indexof isn't on the call chain,
but that inner closure is?
But how can the inner closure be called if not via indexof?


I believe that's exactly what Luke's original example was
illustrating.
On Thu, Oct 02, 2003 at 01:59:26AM -0600, Luke Palmer wrote:

So, I must ask, what does this do:

   sub foo() {
   return my $self = {
   print Block;
   return $self;
   }
   }


foo() returns a closure that contains code that returns from the foo()
subroutine (the line that says return $self)  When that closure is
then called ...

   my $block = foo;
   print Main;
   $block();


... foo() is no longer executing.


That is, the block returns from a function that's not currently
executing.
Will the output be: a)

   Can't 'return' from closure Block

b)

   Main
   Block
   Can't 'return' from closure Block
(just like (a) but runtime)
c)
   Main
   Block
(the block's return returns from the main program, or whatever function
is currently executing)
d)

   Main
   Block
   Main
   Block
   Main
   Block
   ...
(the block closes over the function's return continuation)


I would expect (a) to happen, but (d) has some interesting
possibilities.  And wouldn't (d) be:
Main
Block
Block
Block
...
?

Actually, if your last parenthetical were true, it would be 

Main
Block
End
because though foo()'s return continuation is closed over, it only
gets executed once and then returned.  I.e., to get Block again,
you'd need to execute the return value of $block.
my $block = foo;
print Main;
$b2 = $block();
$b3 = $b2();
$b4 = $b3();# etc.
print End;
or for the infinite version:

my $block = foo;
print Main;
$block = $block() while 1;
print End;  # we never get here
Or am I missing something?
Possibly,  I brought a similar example to Larry a while ago and he said
that creating a closuer and assigning to a variable (or even returning
it), may need to be an exception to the sub required for return
rule, exactly because of this dangling context problem.  So in the above
example, the return is from the local closure not the from foo().
--
[EMAIL PROTECTED]
[EMAIL PROTECTED]


RE: The Block Returns

2003-10-02 Thread Austin Hastings
 -Original Message-
 From: Jonathan Scott Duff [mailto:[EMAIL PROTECTED]
 On Thu, Oct 02, 2003 at 11:39:20AM +0100, Dave Mitchell wrote:
  On Thu, Oct 02, 2003 at 04:15:06AM -0600, Luke Palmer wrote:
   So the question is: What happens when indexof isn't on the call chain,
   but that inner closure is?
 
  But how can the inner closure be called if not via indexof?

 I believe that's exactly what Luke's original example was
 illustrating.

 On Thu, Oct 02, 2003 at 01:59:26AM -0600, Luke Palmer wrote:
  So, I must ask, what does this do:
 
  sub foo() {
  return my $self = {
  print Block;
  return $self;
  }
  }

 foo() returns a closure that contains code that returns from the foo()
 subroutine (the line that says return $self)  When that closure is
 then called ...

  my $block = foo;
  print Main;
  $block();

 ... foo() is no longer executing.

  That is, the block returns from a function that's not currently
  executing.
 
  Will the output be: a)
 
  Can't 'return' from closure Block
 
  b)
 
  Main
  Block
  Can't 'return' from closure Block
 
  (just like (a) but runtime)
  c)
 
  Main
  Block
 
  (the block's return returns from the main program, or whatever function
  is currently executing)
 
  d)
 
  Main
  Block
  Main
  Block
  Main
  Block
  ...
 
  (the block closes over the function's return continuation)

 I would expect (a) to happen, but (d) has some interesting
 possibilities.

I hope not. Otherwise the ability to use anonymous blocks would be severely
impaired.

If there's a list of keywords that can't be used in anonymous blocks, that's
a pretty severe limitation.

And really, is this any worse than an anonymous block that throws
exceptions?

Speaking to the practical side, I have written code that has to disentangle
itself from the failure of a complex startup sequence. I'd love to be able
to build a dynamic exit sequence. (In fact, being able to do Cblock .=
{ more_stuff(); };/C is way up on my list...)


=Austin



Re: The Block Returns

2003-10-02 Thread Jeff Clites
Speaking to the practical side, I have written code that has to 
disentangle
itself from the failure of a complex startup sequence. I'd love to be 
able
to build a dynamic exit sequence. (In fact, being able to do Cblock 
.=
{ more_stuff(); };/C is way up on my list...)
I've wanted to do that sort of thing before, but it seems simpler 
(conceptually and practically) to build up an array of cleanup 
subs/blocks to execute in sequence, rather than to have a .= for 
blocks. (Another reason it's handy to keep them separate is in cases in 
which each needs to return some information--maybe a status which 
determines whether to proceed, etc.)

JEff



Re: The Block Returns

2003-10-02 Thread Luke Palmer
Jeff Clites writes:
 Speaking to the practical side, I have written code that has to 
 disentangle
 itself from the failure of a complex startup sequence. I'd love to be 
 able
 to build a dynamic exit sequence. (In fact, being able to do Cblock 
 .=
 { more_stuff(); };/C is way up on my list...)
 
 I've wanted to do that sort of thing before, but it seems simpler 
 (conceptually and practically) to build up an array of cleanup 
 subs/blocks to execute in sequence, rather than to have a .= for 
 blocks. (Another reason it's handy to keep them separate is in cases in 
 which each needs to return some information--maybe a status which 
 determines whether to proceed, etc.)

But this is already supported, in its most powerful form:

wrap block: { call; other_stuff() }

Luke