castaway has asked for the wisdom of the Perl Monks concerning the following question:

.. apparently doesn't work.. here's a bit of code I was attempting to use, but @args doesn't get set outside of the call to the coderef..
$Commands{'who'} = [ { 'pattern' => '^who (.+)$', #' 'mudindex' => 1, 'commandi2' => sub { @args = ($1, 'who'); print Dumper(\@args) +;}, 'commandi3' => sub { @args = ('who-req', getUser(), $1); print + Dumper(\@rgs);}, 'syntax' => 'who <mudname>' }, { 'pattern' => '^who$', #' 'command' => sub { who_local($userid); }, 'syntax' => 'who' }]; .... my @command = @{$Commands{$com}}; my @args = (); foreach my $commands (@command) { debug("commands: " . Dumper($commands)); ... if(my @res = $input =~ /$commands->{'pattern'}/) { debug("results: " . Dumper(\@res)); if($commands->{'mudindex'}) { ... $commands->{'commandi2'}->(); debug("ARGS: " . Dumper(\@args)); my $result = $i2->send($Users{$userid}{'user'}, @args);
*goes off to think of another way to do it*

C.

Replies are listed 'Best First'.
Re: Using $1,$2 etc in closures..
by chromatic (Archbishop) on Mar 07, 2003 at 21:23 UTC

    Since you declare @args as a lexical outside of the loop and the data structure before the loop, the closures aren't closed over the @args you think they are. :)

    I'd pass @res to your data structure, but I'm paranoid about passing backref variables directly. It bit me in Regex::English or Test::MockObject at least once.

Re: Using $1,$2 etc in closures..
by castaway (Parson) on Mar 07, 2003 at 22:23 UTC
    Hmm.. silly me..
    Just changed it to:
    'commandi2' => sub { return ($1, 'who');},
    and
    @args = $commands->{'commandi2'}->();
    .. Voila, no closures.. (Or it works, at least, which is the main thing..)

    C.

Re: Using $1,$2 etc in closures..
by grantm (Parson) on Mar 07, 2003 at 22:14 UTC

    I think the key point here is that $1, $2, $3 etc are global variables. Referring to a global from within an anonymous sub doesn't make it a closure.

    The following code generates a closure since $x is a lexical in the scope enclosing the anonymous sub:

    sub make_closure { my $x = 1; my $closure = sub { return $x++; }; return $closure; } my $cls = make_closure(); print &$cls; print &$cls; print &$cls;
      Regex match variables aren't actually global. They're... odd. But not global. (Neither are they lexical, though they're mostly lexical. Mostly)

        Oh, well that clears that up then. Thanks :-)

        Whatever they are, I think we can all probably agree they're fairly transient in nature and if they contain anything you want then you ought to be saving it somewhere safe real quick.

Re: Using $1,$2 etc in closures..
by zengargoyle (Deacon) on Mar 08, 2003 at 02:18 UTC

    i was poking around with some code in the recent image size pure perl thread and came up with some similar code.

    use strict; my @test = ( [ '^GIF8..(....)' => sub { return ( GIF => unpack("SS", $_[1]) ); }], [ '^^\xFF\xD8.{4}JFIF' => sub { return ( JPEG => unpack("nn", $1)) if ($_[0] =~ /\xFF\ +xC0...(... .)/s); }], [ '^\x89PNG\x0d\x0a\x1a\x0a' => sub { return ( PNG => unpack("NN", $1)) if ($_[0] =~ /IHDR(. +{8})/s); }], [ 'BM.{16}(.{8})' => sub { return ( BMP => unpack("LL", $_[1]) ); }], ); sub x_image_size { return unless $_[0]; foreach my $test (@test) { my @arg; return ($test->[1]($_[0], @arg)) if (@arg = $_[0] =~ / +$test->[0]/s); } }
Re: Using $1,$2 etc in closures..
by Elian (Parson) on Mar 25, 2003 at 17:40 UTC