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