Closures with $_?

Discussion in 'Perl Misc' started by Michele Dondi, Sep 15, 2004.

  1. The documentation is clear (and I'm not contending this!) about the
    fact that closures are about *lexical* variables.

    Thus I *do* understand why the following doesn't work as (I, for one,
    could have) expected:

    # perl -le 'print map $_->(), map { sub { $_ } } qw/f o o/'
    CODE(0x8137f84)CODE(0x8137f84)CODE(0x8137f84)

    BTW: OTOH I do *not* understand *how* exactly it fails to work, i.e.
    what I actually get. Data::Dumper on

    map { sub { $_ } } ...

    gives me

    $VAR1 = sub { "DUMMY" };
    $VAR2 = $VAR1;
    $VAR3 = $VAR1;

    As a side note indeed this is *not* WIM...

    However, to return to the main theme, using

    map { my $t=$_; sub { $t } } qw/f o o/

    instead does exactly what I want, again as of the documentation. But
    IMHO the latter conveys the psychological feeling of being equivalent
    to the former, just in a more clumsy form.

    So I wonder wether, apart possible technical difficulties, there are
    other issues against the possibility of having closures using $_.


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
     
    Michele Dondi, Sep 15, 2004
    #1
    1. Advertising

  2. Michele Dondi

    Guest

    Michele Dondi <> wrote:
    > The documentation is clear (and I'm not contending this!) about the
    > fact that closures are about *lexical* variables.
    >
    > Thus I *do* understand why the following doesn't work as (I, for one,
    > could have) expected:
    >
    > # perl -le 'print map $_->(), map { sub { $_ } } qw/f o o/'
    > CODE(0x8137f84)CODE(0x8137f84)CODE(0x8137f84)
    >
    > BTW: OTOH I do *not* understand *how* exactly it fails to work, i.e.
    > what I actually get.


    at the time of the outer map, $_ contains a code ref to a subroutine
    which returns $_. So $_->() just returns the value of $_,
    which of course is a code ref and stringifies to look like that.
    I am kind of surprised it is the *same* coderef each time, but I guess
    I shouldn't be surprised. Since code cannot be changed, but only replaced,
    coderefs are essentially immutable and there is no reason not to put all
    copies at the same address.


    > Data::Dumper on
    >
    > map { sub { $_ } } ...
    >
    > gives me
    >
    > $VAR1 = sub { "DUMMY" };
    > $VAR2 = $VAR1;
    > $VAR3 = $VAR1;
    >
    > As a side note indeed this is *not* WIM...


    What about it is not what you meant? The "DUMMY" thing is just
    there as an artifact of Data::Dumper (perldoc Data::Dumper, search
    for DUMMY). The fact that Data::Dumper shows $VAR2=$VAR1 means
    that the reference objects don't just happen to be identical, but
    rather that they are identical because they share the same underlying
    storage.

    > However, to return to the main theme, using
    >
    > map { my $t=$_; sub { $t } } qw/f o o/
    >
    > instead does exactly what I want, again as of the documentation.


    Did you run Data::Dumper on that as well?

    > But
    > IMHO the latter conveys the psychological feeling of being equivalent
    > to the former, just in a more clumsy form.
    >
    > So I wonder wether, apart possible technical difficulties, there are
    > other issues against the possibility of having closures using $_.


    I don't understand what you include in "possible technical difficulties",
    and therefore don't know what issues there are other than the ones you
    already include.

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
     
    , Sep 15, 2004
    #2
    1. Advertising

  3. On 15 Sep 2004 20:31:18 GMT, wrote:

    >> # perl -le 'print map $_->(), map { sub { $_ } } qw/f o o/'
    >> CODE(0x8137f84)CODE(0x8137f84)CODE(0x8137f84)
    >>
    >> BTW: OTOH I do *not* understand *how* exactly it fails to work, i.e.
    >> what I actually get.

    >
    >at the time of the outer map, $_ contains a code ref to a subroutine
    >which returns $_. So $_->() just returns the value of $_,
    >which of course is a code ref and stringifies to look like that.


    OK!!

    >> Data::Dumper on
    >>
    >> map { sub { $_ } } ...
    >>
    >> gives me
    >>
    >> $VAR1 = sub { "DUMMY" };
    >> $VAR2 = $VAR1;
    >> $VAR3 = $VAR1;
    >>
    >> As a side note indeed this is *not* WIM...

    >
    >What about it is not what you meant? The "DUMMY" thing is just
    >there as an artifact of Data::Dumper (perldoc Data::Dumper, search


    I *do* know that.

    Sorry, I reread my post and I realize that definitely I wasn't clear.
    More precisely I could have avoided this thing with Data::Dumper at
    all: I was just trying to say in yet another way that it seems logical
    to me one could expect three anonymous subs each represented by a line
    like the first one above.

    >> map { my $t=$_; sub { $t } } qw/f o o/
    >>
    >> instead does exactly what I want, again as of the documentation.

    >
    >Did you run Data::Dumper on that as well?


    You bet I did!

    >> So I wonder wether, apart possible technical difficulties, there are
    >> other issues against the possibility of having closures using $_.

    >
    >I don't understand what you include in "possible technical difficulties",
    >and therefore don't know what issues there are other than the ones you
    >already include.


    I have not included any technical difficulty, just *evidence* that
    closures are supported only as far as lexical variables are concerned.
    But I don't know why, because I don't know perl internals. So in
    "possible technical difficulties" I include *any* reason p5p's may
    give for e.g.

    map { sub { $_ } } qw/f o o/;

    not being equivalent to (the clumsier)

    map { my $t=$_; sub { $t } } qw/f o o/;


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
     
    Michele Dondi, Sep 16, 2004
    #3
  4. Michele Dondi

    Ben Morrow Guest

    Quoth Michele Dondi <>:
    > So I wonder wether, apart possible technical difficulties, there are
    > other issues against the possibility of having closures using $_.


    A closure has to use lexical variables (only), because it relies on the
    closure being called *after the variables it closes on have gone out of
    (normal) scope*. Globals don't need closures: they are always in scope
    anyway. Consider:

    {
    my $x = 4;
    sub foo {
    my $y = $x;
    $x = shift;
    return $y;
    }
    }

    foo 3;

    When foo is called, it can get at the lexical $x *even though it has
    gone out of scope*, because it is a closure. If $x was a global, there
    would be no need for closure: $x is always available from anywhere.

    You are perhaps not thinking of this sub foo as a closure; it is,
    however. The situation you probably have in mind:

    my @a;
    for my $x (1..4) {
    push @a, sub { $x };
    }
    print map $_->(), @a;

    is slightly more complicated because the scope that is the 'for' loop
    runs four times, and each one is *a completely separate scope* from the
    others. That is, there are four different variables named '$x' which do
    not affect one another, just as there are two here:

    {
    $x = 1;
    }
    {
    print $x;
    }

    ..

    So (and I apologise if you actually understood all this already, but I
    got the impression from your example that you didn't), you question is
    not 'can closures be made to close on $_' but rather 'can $_ be made
    lexical'. The answer to that is that it could except it would break
    programs expecting it to be global, so it won't happen till Perl6 (where
    $_ is, indeed, lexical, and thus closed upon by closures).

    Ben

    --
    Musica Dei donum optimi, trahit homines, trahit deos. |
    Musica truces mollit animos, tristesque mentes erigit. |
    Musica vel ipsas arbores et horridas movet feras. |
     
    Ben Morrow, Sep 18, 2004
    #4
  5. Michele Dondi

    Joe Smith Guest

    Michele Dondi wrote:

    > I have not included any technical difficulty, just *evidence* that
    > closures are supported only as far as lexical variables are concerned.
    > But I don't know why, because I don't know perl internals.


    Closures require at least one lexical variable.
    Otherwise it would not be able to distinguish one closure from another.

    Just accept the restriction that closures need lexical variables and
    move on.
    -Joe
     
    Joe Smith, Sep 19, 2004
    #5
  6. Michele Dondi

    Guest

    Michele Dondi <> wrote:

    > >> So I wonder wether, apart possible technical difficulties, there are
    > >> other issues against the possibility of having closures using $_.

    > >
    > >I don't understand what you include in "possible technical
    > >difficulties", and therefore don't know what issues there are other than
    > >the ones you already include.

    >
    > I have not included any technical difficulty, just *evidence* that
    > closures are supported only as far as lexical variables are concerned.


    Maybe I'm overstepping my knowledge, or getting bogged down in semantics,
    but I would say that closures are supported for all variables. It is just
    that closures are kind of trivial when they don't include any lexical
    variables.


    > But I don't know why, because I don't know perl internals. So in
    > "possible technical difficulties" I include *any* reason p5p's may
    > give for e.g.
    >
    > map { sub { $_ } } qw/f o o/;


    Here, $_ is the same variable each time the sub is defined, so all
    three subs are effectively equivalent. (The perl implementation is
    smart enough to realize this, and makes them exactly equivalent, not
    just effectively equivalent; but that is just an optimization, not
    a fundamental difference).

    The problem you were having is that you kept overwriting the value of
    $_ between the time the sub was defined and the time it was used.

    > not being equivalent to (the clumsier)
    >
    > map { my $t=$_; sub { $t } } qw/f o o/;


    Here, $t is a different variable each time the sub is defined, so each of
    the resultant closures are different. Each one contains a (different)
    internal reference to a (different) now-anonymous variable, formerly known
    as $t.

    The fact that the closure contains a reference to the variables formerly
    known as $t keeps the ref counts above zero, so those variables can't
    disappear as long as the closures themselves are around. (This point is
    irrelevant to package variables, since they don't disappear anyway until
    the end of the program anyway.) Furthermore, the closures' references are
    the only references to those variables, once you leave the scope of the map
    block, so the variables are unlikely to get stepped on like $_ was.


    If you change the code just a bit by taking the "my" out of the loop:

    my $t;
    print map {$_->()} map { $t=$_; sub { $t } } qw/f o o/;

    Now, each closures refers to the same $t, just as like in your first case
    they all refer to the same $_. All of the subs are effectively equivalent
    (but the perl implementation doesn't realize this, so each coderef has a
    different address). And that one variable $t gets walked all over, but not
    as badly as $_ did in the first example.

    to make it even more like the first example:

    my $t;
    print map {$t=$_; $_->()} map { $t=$_; sub { $t } } qw/f o o/;


    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
     
    , Sep 19, 2004
    #6
  7. On 19 Sep 2004 04:42:19 GMT, wrote:

    >> I have not included any technical difficulty, just *evidence* that
    >> closures are supported only as far as lexical variables are concerned.

    >
    >Maybe I'm overstepping my knowledge, or getting bogged down in semantics,
    >but I would say that closures are supported for all variables. It is just
    >that closures are kind of trivial when they don't include any lexical
    >variables.


    This is what I meant.

    [lengthy explanation snipped]

    TY for the explanation.


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
     
    Michele Dondi, Sep 19, 2004
    #7
  8. On Sat, 18 Sep 2004 23:46:36 +0100, Ben Morrow <>
    wrote:

    >So (and I apologise if you actually understood all this already, but I


    I'd say that I "sort of" understood all this in the sense that (IMHO)
    I already knew all this much better than I may have given the
    impression of. Said this, other posters already made the point and
    clarified things up, so in some sense yes: your explanation was
    redundant. But you know: repetita iuvant! And all this may be helpful
    for others too.

    >got the impression from your example that you didn't), you question is
    >not 'can closures be made to close on $_' but rather 'can $_ be made
    >lexical'. The answer to that is that it could except it would break
    >programs expecting it to be global, so it won't happen till Perl6 (where


    Indeed I'm aware that hoping for $_ to be made lexical would be too
    much. And to be fair I wouldn't regard it as a Good Thing(TM), from a
    Perl5's perspective.

    Rather I wonder wether, apart possible technical difficulties (as of
    my OP), it would be possible to add still some more magic to $_ in
    order to make it behave like it were a lexical var in all those
    situations in which something is automatically aliased to it (i.e.
    C<for>, C<map>, etc.)

    After all

    map { "\$_=<$_>" } @input;

    and

    map { my $t=$_; "\$_=<$t>" } @input;

    are perfectly equivalent, so I *think* that one could reasonably
    wonder why

    map { sub { $_ } } @input;

    and

    map { my $t=$_; sub { $t } } @input;

    are not. Then the answer, as you all have been explaining and
    stressing, is that (to sum up as briefly as possible) "a sub is not a
    string, period". But then there are situations when one would want to
    achieve the effect of the second example while I can't see any actual
    use for the first. So IMHO it would be a big, typically perlish
    dwimmery to have the first one behave like the second one.


    Thanks,
    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
     
    Michele Dondi, Sep 20, 2004
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Kasper B. Graversen

    Closures in python

    Kasper B. Graversen, Sep 18, 2003, in forum: Python
    Replies:
    11
    Views:
    703
    David Eppstein
    Sep 21, 2003
  2. Gustavo Niemeyer

    Closures

    Gustavo Niemeyer, Apr 29, 2004, in forum: Python
    Replies:
    1
    Views:
    342
    Michele Simionato
    Apr 30, 2004
  3. Michael Sparks

    Re: Closures

    Michael Sparks, Apr 29, 2004, in forum: Python
    Replies:
    1
    Views:
    349
    Robert Kern
    Apr 30, 2004
  4. Alexander May

    Misunderstanding about closures

    Alexander May, Jun 7, 2004, in forum: Python
    Replies:
    14
    Views:
    604
    Jacek Generowicz
    Jun 17, 2004
  5. Robert Brewer

    RE: Misunderstanding about closures

    Robert Brewer, Jun 7, 2004, in forum: Python
    Replies:
    1
    Views:
    425
    Hung Jung Lu
    Jun 7, 2004
Loading...

Share This Page