in reply to Re^6: Combinations of lists, etc
in thread Combinations of lists to a hash

Further to LanX's reply:   Consider the two statements
    @ra = ({a=>1, b=>2}, {a=>1, b=>2});
and
    @ra = ({a=>1, b=>2}) x 2;
In the first, two different anonymous array references are being constructed. In the second, a single anonymous array reference is constructed and then repeated twice.

c:\@Work\Perl\monks\tel2>perl -wMstrict -MData::Dump -le "my @ra = ({a=>1, b=>2}, {a=>1, b=>2}); print qq{@ra}; ;; @ra = ({a=>1, b=>2}) x 2; print qq{@ra}; " HASH(0x1555cdc) HASH(0x1555e50) HASH(0x1555e20) HASH(0x1555e20)

In

c:\@Work\Perl\monks\tel2>perl -wMstrict -MData::Dump -le "my %hash; ;; @hash{ qw(key1 key2) } = ({a=>1, b=>2},{a=>1,b=>2}); dd \%hash; ;; @hash{ qw(key1 key2) } = ({a=>1, b=>2}) x 2; dd \%hash; " { key1 => { a => 1, b => 2 }, key2 => { a => 1, b => 2 } } do { my $a = { key1 => { a => 1, b => 2 }, key2 => 'fix' }; $a->{key2} = $a->{key1}; $a; }
the  do { ... } business with the  'fix' in the second dd instance just reflects the fact that a hash reference  $a is built that needs to have its  'key2' key "fixed" later by a  $a->{key2} = $a->{key1}; statement that makes the value of 'key2' the same as 'key1': they're the same reference. (Update:  dd works by generating source code that | source code text that, when run thru eval, will reproduce the structure of the data being dumped.)

Update: Clarified the update remark about  dd per LanX's comment here. Thanks, LanX!


Give a man a fish:  <%-{-{-{-<

Replies are listed 'Best First'.
Re^8: Combinations of lists, etc
by LanX (Saint) on Oct 07, 2019 at 14:29 UTC
    > Further to LanX's reply:

    And further to your reply ... ;-)

    plain printing of the references reveals that the last are identical objects

    DB<61> @ra = ({a=>1, b=>2}, {a=>1, b=>2}); DB<62> print $_ for @ra HASH(0x35a4090)HASH(0x35a3ae8) # different IDs DB<63> @ra = ({a=>1, b=>2}) x 2; DB<64> print $_ for @ra HASH(0x35a3eb0)HASH(0x35a3eb0) # same IDs DB<65>

    > Update: dd works by generating source code that will reproduce the structure of the data being dumped.

    ... when run thru eval .

    There seems to be no better generic syntax to reproduce the case of duplicated references, than stuffing a fix placeholder string into it and fixing it later.

    An for completeness, here code to clone the hashes instead of copying their refs

    my $value = { a=>1, b=>2 }; # curly brackets to assign hashref! $hash{$_} = { %$value } for @keys; ### or alternatively my %value = ( a=>1, b=>2 ); # round brackets to assign list! $hash{$_} = { %value } for @keys;

    this kind of cloning works because % returns a list in listcontext, which is packed again into a new { hash }

    DB<78> x %$value 0 'a' 1 1 2 'b' 3 2 DB<79>

    debugger demo

    DB<72> x @keys 0 'Prefix1=A:b:1' 1 'Prefix1=A:b:2' 2 'Prefix1=A:c:1' 3 'Prefix1=A:c:2' DB<73> x $value = {a=>1, b=>2}; 0 HASH(0x35a48e8) 'a' => 1 'b' => 2 DB<74> $hash{$_} = { %$value } for @keys; DB<75> x \%hash 0 HASH(0x3598330) 'Prefix1=A:b:1' => HASH(0x35a50b8) 'a' => 1 'b' => 2 'Prefix1=A:b:2' => HASH(0x35a4c18) # <--- differing IDs 'a' => 1 'b' => 2 'Prefix1=A:c:1' => HASH(0x35a46a8) 'a' => 1 'b' => 2 'Prefix1=A:c:2' => HASH(0x35a4a50) 'a' => 1 'b' => 2 DB<77>

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

      And further to your further to my further to... wait... what?!? :)

      $hash{$_} = { %$value } for @keys;
      ...
      $hash{$_} = { %value } for @keys;

      I always think it's worth pointing out in discussions on this topic that something like  { %$value } or  { %value } only does a shallow copy.


      Give a man a fish:  <%-{-{-{-<

        further4: ;-)

        > only does a shallow copy.

        yes, but at this point maybe already too much information for the OP.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Re^8: Combinations of lists, etc
by tel2 (Pilgrim) on Oct 07, 2019 at 21:19 UTC
    Thanks for that, AnomalousMonk.

    "In the first, two different anonymous array references are being constructed. In the second, a single anonymous array reference is constructed and then repeated twice."

    So how can we use this concise & convenient "x 2" syntax to generate the former?  I've just proposed a workaround here, but maybe there's a cleaner method.

    Update: It looks as if I don't actually need an alternative, because the later should work for my needs, since I'll only be reading it, according to LanX.  But I'm still interested if you know of a concise efficient alternative, which would allow reading & writing.

      "In the first, two different anonymous array references are being constructed. In the second, ..."

      So how can we use this concise & convenient "x 2" syntax to generate the former?

      I think you understand this already, so I'll answer just for the sake of completeness: You can't. The  x operator (see perlop) makes exact copies either of the elements of a list, the copies of which form another list, or of a string | a scalar, which is a string or stringized "thing" (number, reference, whatever), the copies of which are then contatenated together. And it's not possible to get different things if you're making exact copies of a thing (if you're doing it right).


      Give a man a fish:  <%-{-{-{-<

        Well said, LanX.

        So would it be true to say that when taking such "exact" copies of a string, you can modify the copy without affecting the original, but this is not the case when taking such "exact" copies of things like hash keys & values, because the copy will be some kind of reference to the original?

      > But I'm still interested if you know of a concise efficient alternative, which would allow reading & writing.

      We already showed you:

      $hash{$_} = { %$value } for @keys;

      or

      $hash{$_} = { %value } for @keys;

      The only concise alternative which comes to mind is

      @hash{ @keys } = map { { %value } } @keys

      But it's neither shorter nor easier to read.

      Cheers Rolf

      update

      But honestly you should stick to syntax you understand, even if it takes some lines more.

        Thanks for that, again, LanX.