Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Strange error message with anon subroutine

10 views
Skip to first unread message

Ovid

unread,
Dec 13, 2006, 2:31:33 PM12/13/06
to perl6...@perl.org
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.

Also, I noticed I accidentally left off the final semi-colon on the do
block. It ran anyway and that surprised me.

Cleaner ways of writing that code are welcome, too.

Cheers,
Ovid

--

Buy the book -- http://www.oreilly.com/catalog/perlhks/
Perl and CGI -- http://users.easystreet.com/ovid/cgi_course/

Larry Wall

unread,
Dec 13, 2006, 3:00:06 PM12/13/06
to perl6...@perl.org
On Wed, Dec 13, 2006 at 11:31:33AM -0800, Ovid wrote:
: In trying to compress a list, I wrote the following code:

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

Gaal Yahas

unread,
Dec 13, 2006, 3:19:54 PM12/13/06
to Ovid, perl6...@perl.org
On Wed, Dec 13, 2006 at 11:31:33AM -0800, Ovid wrote:
> *** 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.

Perl 6 differentiates between a bare Code and Routine objects. Replacing
"->" with "sub" should get you what you want.

--
Gaal Yahas <ga...@forum2.org>
http://gaal.livejournal.com/

0 new messages