Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW

closure question

by nop (Hermit)
on Feb 02, 2001 at 00:47 UTC ( #55832=perlquestion: print w/replies, xml ) Need Help??
nop has asked for the wisdom of the Perl Monks concerning the following question:

I want an array of anonymous arrays, each with some data and a code ref. The coderef defaults to the identity function; return the scalar that was sent. (This gets overriden as needed.)
use strict; use Data::Dumper; my %x = map { $_ => [$_, sub {shift;}]} qw(a b c); print Dumper(\%x);
The result isn't what I expected:
$VAR1 = { 'a' => [ 'a', sub { "DUMMY" } ], 'b' => [ 'b', $VAR1->{'a'}[1] ], 'c' => [ 'c', $VAR1->{'a'}[1] ] };
Why do "b" and "c" share the same coderef as "a"? I had expected each would get a reference to their own sub.... Confused...


Replies are listed 'Best First'.
Re: closure question
by chipmunk (Parson) on Feb 02, 2001 at 01:01 UTC
    Your sub isn't really a closure, because it doesn't reference any lexical variables that will go out of scope. Thus, there is no need for Perl to allocate a separate subroutine each time.

    On the other hand, if you changed your code to:

    use strict; use Data::Dumper; my %x = map { my $a; $_ => [$_, sub {$a; shift;}] } qw(a b c); print Dumper(\%x);
    then the sub becomes a closure, and you get three distinct subroutines, each one refering to a distinct instance of $a.
Re: closure question
by Fastolfe (Vicar) on Feb 02, 2001 at 01:53 UTC
    Is there any reason you need the subroutine to be separate for each element? Let perl compile it once and use the same coderef for each element if you can, as that saves on memory and work. That doesn't prevent you from overriding those definitions with another coderef if you need to.

    Also, don't be confused by the "DUMMY" bit (not that you've given any indication that you are confused -- mainly this is for the benefit of others). Data::Dumper can't deal with coderefs, so it just inserts a subroutine that is effectively a no-op, and returning "DUMMY" is as good as anything else.

      Good point. I was getting confused by the Dumper representation: I was worried that if I changed the 'a' coderef, then 'b' and 'c' would point to garbage. (Repeat often: Perl isn't C! Perl Isn't C! Perl isn't C! Hurrah.) The way I understand reference counting, the anon sub will stay around until the last reference to it goes away. The way Dumper printed it, I was incorrectly thinking that the 'a' coderef was somehow "primary", and the 'b' and 'c' refs were somehow subordinate.

      As for writing subroutines that don't seem to do much... hey, that's my login name, nop!
Re: closure question
by runrig (Abbot) on Feb 02, 2001 at 01:00 UTC
    The output from Dumper is funny, but the coderefs work for this:
    #!/usr/local/bin/perl -l -w use Data::Dumper; my @arr = map {my $var=$_; [$_, sub {$var}]} qw(a b c); print Dumper(\@arr); print &{$arr[0][1]}; print &{$arr[1][1]};
    Oh, I notice you wanted a hash, well I'm sure you can figure it out :)
    And this is probably not what you want anyway... I think I'll refrain from posting the rest of today :(

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://55832]
Approved by root
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (6)
As of 2018-07-16 03:29 GMT
Find Nodes?
    Voting Booth?
    It has been suggested to rename Perl 6 in order to boost its marketing potential. Which name would you prefer?

    Results (330 votes). Check out past polls.