Curious corner cases concerning closure cloning

2006-08-14 Thread Luke Palmer

What do these do?

 for 1,2 {
 my $code = {
 my $x;
 BEGIN { $x = 42 }
 $x;
 };
 say $code();
 }

 for 1,2 {
 my $code = {
 state $x;
 BEGIN { $x = 42 }  # mind you, not FIRST
 $x++;
 };
 say $code();
 say $code();
 }

 for 1,2 - $x {
 END { say $x }
 }

Thanks,
Luke


Re: Curious corner cases concerning closure cloning

2006-08-14 Thread Yuval Kogman
On Mon, Aug 14, 2006 at 16:01:47 +, Luke Palmer wrote:
 What do these do?

Intuition based answers:

  for 1,2 {
  my $code = {
  my $x;
  BEGIN { $x = 42 }
  $x;
  };
  say $code();
  }

I think the closure would be emitted equivalently to my $x = 42, or
perhaps $x is not in the BEGIN blocks scope at all.

  for 1,2 {
  my $code = {
  state $x;
  BEGIN { $x = 42 }  # mind you, not FIRST
  $x++;
  };
  say $code();
  say $code();
  }

Again, assuming the BEGIN { } body is not even compile but it's side
effect is meaningful, this is the same as 

state $x = 42;

but starting to get a little tougher to justify.

Perhaps it does that, but also emits a warning e.g. 'implicit
initial value for future-scoped lexical' or something like that.


  for 1,2 - $x {
  END { say $x }
  }

undef, because END is like a declaration putting the closure in some
global, and doesn't actually happen at runtime.

Otoh

for 1,2 - $x {
state $y = $x;
END { say $y }
}

Might work

-- 
  Yuval Kogman [EMAIL PROTECTED]
http://nothingmuch.woobling.org  0xEBD27418



pgp2ibIxnkvaI.pgp
Description: PGP signature


Re: Curious corner cases concerning closure cloning

2006-08-14 Thread Jonathan Scott Duff
On Mon, Aug 14, 2006 at 04:01:47PM +, Luke Palmer wrote:
 What do these do?
 
  for 1,2 {
  my $code = {
  my $x;
  BEGIN { $x = 42 }
  $x;
  };
  say $code();
  }

Assuming that variables are available immediately as
they are parsed and that BEGIN blocks disappear as soon as they
execute, I'd expect that the first $code would be equivalent to 

my $code = { my $x = 42; $x; };

and the second code would be equivalent to

my $code = { my $x ; $x; };

So, I guess the output would be 

42
# this line intentionally left blank  :-)


  for 1,2 {
  my $code = {
  state $x;
  BEGIN { $x = 42 }  # mind you, not FIRST
  $x++;
  };
  say $code();
  say $code();
  }

Same thing here, except because it's a state variable, it keeps it's
value between invocations, so the output would be:

42
43
# again, blank on purpose
1

  for 1,2 - $x {
  END { say $x }
  }

For this one I'd guess that a solitary 2 is output.  The END block
closed over the $x and the last value that $x obtained was 2.

my humble guesses,

-Scott
-- 
Jonathan Scott Duff
[EMAIL PROTECTED]


[svn:perl6-synopsis] r10940 - doc/trunk/design/syn

2006-08-14 Thread larry
Author: larry
Date: Mon Aug 14 12:36:02 2006
New Revision: 10940

Modified:
   doc/trunk/design/syn/S02.pod

Log:
Clarified that comments may not contain unspace.  agentzh++ and luqui++.


Modified: doc/trunk/design/syn/S02.pod
==
--- doc/trunk/design/syn/S02.pod(original)
+++ doc/trunk/design/syn/S02.podMon Aug 14 12:36:02 2006
@@ -12,9 +12,9 @@
 
   Maintainer: Larry Wall [EMAIL PROTECTED]
   Date: 10 Aug 2004
-  Last Modified: 10 Aug 2006
+  Last Modified: 14 Aug 2006
   Number: 2
-  Version: 63
+  Version: 64
 
 This document summarizes Apocalypse 2, which covers small-scale
 lexical items and typological issues.  (These Synopses also contain
@@ -210,6 +210,22 @@
 
 =item *
 
+An unspace may contain a comment, but a comment may not contain an unspace.
+In particular, end-of-line comments do not treat backslash as significant.
+If you say:
+
+#\ (...
+
+it is an end-of-line comment, not an embedded comment.  Write:
+
+\ #(
+   ...
+   )
+
+to mean the other thing.
+
+=item *
+
 In general, whitespace is optional in Perl 6 except where it is needed
 to separate constructs that would be misconstrued as a single token or
 other syntactic unit.  (In other words, Perl 6 follows the standard


[svn:perl6-synopsis] r10942 - doc/trunk/design/syn

2006-08-14 Thread larry
Author: larry
Date: Mon Aug 14 17:53:44 2006
New Revision: 10942

Modified:
   doc/trunk/design/syn/S04.pod
   doc/trunk/design/syn/S06.pod

Log:
FIRST renamed to START. (FIRST now does loop initialization only.)
Minor cleanup of MAIN verbiage.


Modified: doc/trunk/design/syn/S04.pod
==
--- doc/trunk/design/syn/S04.pod(original)
+++ doc/trunk/design/syn/S04.podMon Aug 14 17:53:44 2006
@@ -615,26 +615,32 @@
 called at various times, and some of them respond to various control
 exceptions and exit values:
 
-  BEGIN {...}* at compile time, ASAP
-  CHECK {...}* at compile time, ALAP
-   INIT {...}* at run time, ASAP
-END {...}  at run time, ALAP
-  FIRST {...}* at first block entry time
-  ENTER {...}* at every block entry time 
+  BEGIN {...}* at compile time, ASAP, only ever runs once
+  CHECK {...}* at compile time, ALAP, only ever runs once
+   INIT {...}* at run time, ASAP, only ever runs once
+END {...}  at run time, ALAP, only ever runs once
+
+  START {...}* on first ever execution, once per closure clone
+
+  ENTER {...}* at every block entry time, repeats on loop blocks.
   LEAVE {...}  at every block exit time 
-   KEEP {...}  at every successful block exit
-   UNDO {...}  at every unsuccessful block exit
-   NEXT {...}  at loop continuation time
-   LAST {...}  at loop termination time
-PRE {...}  assert precondition at every block entry
-   POST {...}  assert postcondition at every block exit
-  CATCH {...}  catch exceptions
-CONTROL {...}  catch control exceptions
+   KEEP {...}  at every successful block exit, part of LEAVE queue
+   UNDO {...}  at every unsuccessful block exit, part of LEAVE queue
+
+  FIRST {...}* at loop initialization time, before any ENTER
+   NEXT {...}  at loop continuation time, after any LEAVE
+   LAST {...}  at loop termination time, after any LEAVE
+
+PRE {...}  assert precondition at every block entry, before any
+   POST {...}  assert postcondition at every block exit, after any
+
+  CATCH {...}  catch exceptions, before LEAVE
+CONTROL {...}  catch control exceptions, before LEAVE
 
 Those marked with a C* can also be used within an expression:
 
 my $compiletime = BEGIN { localtime };
-our $temphandle = FIRST { maketemp() };
+our $temphandle = START { maketemp() };
 
 Code that is generated at run time can still fire off CCHECK
 and CINIT blocks, though of course those blocks can't do things that
@@ -644,25 +650,26 @@
 These have the advantage of passing the variable in question into
 the closure as its topic:
 
-my $r will first { .set_random_seed() };
+my $r will start { .set_random_seed() };
 our $h will enter { .rememberit() } will undo { .forgetit() };
 
-Apart from CCATCH and CCONTROL, which can only occur once, most of
-these can occur multiple times within the block.  So they aren't really
-traits, exactly--they add themselves onto a list stored in the
-actual trait.  So if you examine the CENTER trait of a block, you'll
-find that it's really a list of closures rather than a single closure.
+Apart from CCATCH and CCONTROL, which can only occur once, most
+of these can occur multiple times within the block.  So they aren't
+really traits, exactly--they add themselves onto a list stored in the
+actual trait (except for CSTART, which executes inline).  So if you
+examine the CENTER trait of a block, you'll find that it's really
+a list of closures rather than a single closure.
 
-The semantics of CINIT and CFIRST are not equivalent to each
+The semantics of CINIT and CSTART are not equivalent to each
 other in the case of cloned closures.  An CINIT only runs once for
-all copies of a cloned closure.  A CFIRST runs separately for each
+all copies of a cloned closure.  A CSTART runs separately for each
 clone, so separate clones can keep separate state variables:
 
 our $i = 0;
 ...
-$func = { state $x will first{$i++}; dostuff($i) };
+$func = { state $x will start { $x = $i++ }; dostuff($i) };
 
-But Cstate automatically applies first semantics to any initializer,
+But Cstate automatically applies start semantics to any initializer,
 so this also works:
 
 $func = { state $x = $i++; dostuff($i) }
@@ -671,6 +678,12 @@
 previous, and each clone maintains its own state of C$x, because that's
 what Cstate variables do.
 
+Even in the absence of closure cloning, CINIT runs before the
+mainline code, while CSTART puts off the initialization till the
+last possible moment, then runs exactly once, and caches its value
+for all subsequent calls (assuming it wasn't called in void context,
+in which case the CSTART is evaluated once only for its side effects).
+
 All of these trait