On Wed, Dec 13, 2006 at 11:31:33AM -0800, Ovid wrote: : In trying to compress a list, I wrote the following code: : : my $compress = do { : my $previous; : $compress = -> $x { : if !defined $previous or $x ne $previous { : $previous = $x; : $x; : } : else { : (); : } : }; : } : my @compressed = map $compress, <a a a a b c c a a d e e e e>; : @compressed.say; : : That's a bit more verbose than I intended, but that's partially because : of this: : : my $compress = do { : my $previous; : $compress = -> $x { : if !defined $previous or $x ne $previous { : $previous = $x; : return $x; : } : else { : return (); : } : }; : }; : : As soon as I put the return statements in an anonymous subroutine, I : get this error message: : : *** Cannot use this control structure outside a 'routine' structure : at 99.pugs line 103, column 13-22 : : Take out the returns, and it works fine. Can someone tell me what I'm : missing? Is this a bug.
Nope, spec. S06 says: [Pointy block] also behaves like a block with respect to control exceptions. If you C<return> from within a pointy block, it will return from the innermost enclosing C<sub> or C<method>, not the block itself. It is referenced by C<&?BLOCK>, not C<&?ROUTINE>. See also the section in S04 discussing control exceptions, where it says: A C<return> always exits from the lexically surrounding sub or method definition (that is, from a function officially declared with the C<sub>, C<method>, or C<submethod> keywords). Pointy blocks and bare closures are transparent to C<return>. So all you really need to do is change the pointy to an official sub: my $compress = do { my $previous; $compress = sub ($x) { if !defined $previous or $x ne $previous { $previous = $x; return $x; } else { return (); } } } : Also, I noticed I accidentally left off the final semi-colon on the do : block. It ran anyway and that surprised me. S04: Outside of any kind of expression brackets, a final closing curly on a line (not counting whitespace or comments) always reverts to the precedence of semicolon whether or not you put a semicolon after it. Larry