pseudo hash syntax in 5.10

Discussion in 'Perl Misc' started by Patrick Viet, Feb 23, 2009.

  1. Patrick Viet

    Patrick Viet Guest

    Hello,

    I've been using a weird syntax to assign elements from a hash to array
    for several years now. Doesn't work in 5.10. I saw the changelog and it
    said pseudo-hashes didn't exist. Didn't know it was pseudo hash I was
    using... Anybody knows how to adapt my code ?

    Here it is :

    $h = {
    a => 'data1',
    b => 'data2',
    c => 'data3',
    ...
    };

    my ($data_a,$data_b) = @{$h}{'a','b'};

    Any other idea to do this ? Obviously an alternative syntax would be :

    my $data_a = $h->{'a'};
    my $data_b = $h->{'b'};

    But this kind of sucks because my real usage is like this :

    (in sql req)
    while(my $href = $sth->fetchrow_hashref) {
    my $key = join('|',@{$href}{@cols_primary});

    Which is really practical ...

    Any ideas ?

    Thanks,

    --
    Patrick Viet
     
    Patrick Viet, Feb 23, 2009
    #1
    1. Advertising

  2. Patrick Viet

    Matija Papec Guest

    Patrick Viet wrote:
    > Hello,
    >
    > I've been using a weird syntax to assign elements from a hash to array
    > for several years now. Doesn't work in 5.10. I saw the changelog and it
    > said pseudo-hashes didn't exist. Didn't know it was pseudo hash I was
    > using...


    You were using hash slice on the regular hash, nothing to worry about.

    > Here it is :
    >
    > $h = {
    > a => 'data1',
    > b => 'data2',
    > c => 'data3',
    > ...
    > };
    >
    > my ($data_a,$data_b) = @{$h}{'a','b'};


    This should also work under 5.10, what kind of error do you get when
    reading hash slice?
     
    Matija Papec, Feb 23, 2009
    #2
    1. Advertising

  3. Patrick Viet <> wrote:
    > Hello,
    >
    > I've been using a weird syntax to assign elements from a hash to array
    > for several years now.



    The "weird syntax" looks like a "hash slice" rather than a "pseudo hash"
    to me...


    > Doesn't work in 5.10.



    Have you seen the Posting Guidelines that are posted here frequently?

    Are you getting an error message?

    If so, what is the exact text of the message?

    If not, then what does "doesn't work" mean when you say it?

    That is, what were you expecting it to do, and what is it doing instead?


    > I saw the changelog and it
    > said pseudo-hashes didn't exist. Didn't know it was pseudo hash I was
    > using...



    pseudo-hashes apply only to arrays.

    There is only one array in all of the code that you've posted.

    Is the 1st element in @cols_primary a reference to a hash?

    If not, then there are no pseudo hashes here...


    > Anybody knows how to adapt my code ?
    >
    > Here it is :
    >
    > $h = {
    > a => 'data1',
    > b => 'data2',
    > c => 'data3',
    > ...
    > };
    >
    > my ($data_a,$data_b) = @{$h}{'a','b'};



    That is a vanilla hash slice.

    I don't expect that hash slices were broken in 5.10 (I don't have 5.10 yet).


    > Any other idea to do this ? Obviously an alternative syntax would be :
    >
    > my $data_a = $h->{'a'};
    > my $data_b = $h->{'b'};
    >
    > But this kind of sucks because my real usage is like this :
    >
    > (in sql req)
    > while(my $href = $sth->fetchrow_hashref) {
    > my $key = join('|',@{$href}{@cols_primary});
    >
    > Which is really practical ...



    You have not shown us the contents of @cols_primary, so we cannot
    comment on this piece of code.


    --
    Tad McClellan
    email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"
     
    Tad J McClellan, Feb 23, 2009
    #3
  4. Patrick Viet

    Patrick Viet Guest

    > Have you seen the Posting Guidelines that are posted here frequently?

    No sorry, i'm not a thorough usenet poster, I didn't know there was such
    a thing. But that I understand :

    > Have you seen the Posting Guidelines that are posted here frequently?
    > Are you getting an error message?
    > If so, what is the exact text of the message?
    > If not, then what does "doesn't work" mean when you say it?
    > That is, what were you expecting it to do, and what is it doing
    > instead?


    So I'll post some more detail.

    BTW I got the stuff to work. But I don't understand why it doesn't work
    anymore while it did in 5.8 ...

    Here is my full test :

    --------------------
    #!/usr/bin/perl

    use warnings;
    use strict;

    my $h = {
    a => 'test1',
    b => 'test2',
    c => 'test3',
    };

    my @list = qw(a b);

    my ($var1,$var2) = @{%$h}{@list};

    print "var1 : $var1 $var2\n";
    --------------------

    $ ./test
    Can't use string ("3/8") as a HASH ref while "strict refs" in use at
    ../test line 14.

    And if I take out the % on the my var1,var2 line, I get what I expected:

    $ ./test
    var1 : test1 test2

    I've solved my problem in the sense that my software can work again, but
    I don't understand what that message is, why it stopped working in 5.10,
    and where that 3/8 crap comes from (?!)


    Other script that produces the same result without hash ref :


    --------------------
    #!/usr/bin/perl

    use warnings;
    use strict;

    my %h = (
    a => 'test1',
    b => 'test2',
    c => 'test3',
    );

    my @list = qw(a b);

    my ($var1,$var2) = @{\%h}{@list};

    print "var1 : $var1 $var2\n";

    --------------------

    Isn't there anything less crappy than \% that's valid in 5.10 ? I tried
    quite a bit of things without getting my "var1 : test1 test2" expected
    result.

    --
    Patrick Viet
     
    Patrick Viet, Feb 23, 2009
    #4
  5. Patrick Viet

    Patrick Viet Guest

    > Have you seen the Posting Guidelines that are posted here frequently?

    No sorry, i'm not a thorough usenet poster, I didn't know there was such
    a thing. But that I understand :

    > Have you seen the Posting Guidelines that are posted here frequently?
    > Are you getting an error message?
    > If so, what is the exact text of the message?
    > If not, then what does "doesn't work" mean when you say it?
    > That is, what were you expecting it to do, and what is it doing
    > instead?


    So I'll post some more detail.

    BTW I got the stuff to work. But I don't understand why it doesn't work
    anymore while it did in 5.8 ...

    Here is my full test :

    --------------------
    #!/usr/bin/perl

    use warnings;
    use strict;

    my $h = {
    a => 'test1',
    b => 'test2',
    c => 'test3',
    };

    my @list = qw(a b);

    my ($var1,$var2) = @{%$h}{@list};

    print "var1 : $var1 $var2\n";
    --------------------

    $ ./test
    Can't use string ("3/8") as a HASH ref while "strict refs" in use at
    ../test line 14.

    And if I take out the % on the my var1,var2 line, I get what I expected:

    $ ./test
    var1 : test1 test2

    I've solved my problem in the sense that my software can work again, but
    I don't understand what that message is, why it stopped working in 5.10,
    and where that 3/8 crap comes from (?!)


    Other script that produces the same result without hash ref :


    --------------------
    #!/usr/bin/perl

    use warnings;
    use strict;

    my %h = (
    a => 'test1',
    b => 'test2',
    c => 'test3',
    );

    my @list = qw(a b);

    my ($var1,$var2) = @{\%h}{@list};

    print "var1 : $var1 $var2\n";

    --------------------

    Isn't there anything less crappy than \% that's valid in 5.10 ? I tried
    quite a bit of things without getting my "var1 : test1 test2" expected
    result.

    --
    Patrick Viet
     
    Patrick Viet, Feb 23, 2009
    #5
  6. Patrick Viet

    Patrick Viet Guest

    sorry for double post i'm not so good at using thunderbird
     
    Patrick Viet, Feb 23, 2009
    #6
  7. Patrick Viet

    Matija Papec Guest

    Patrick Viet wrote:

    > my ($var1,$var2) = @{\%h}{@list};


    less crappy version:
    my ($var1,$var2) = @h{@list};

    ;)

    > print "var1 : $var1 $var2\n";
    >
    > --------------------
    >
    > Isn't there anything less crappy than \% that's valid in 5.10 ? I tried
    > quite a bit of things without getting my "var1 : test1 test2" expected
    > result.
    >
     
    Matija Papec, Feb 23, 2009
    #7
  8. Patrick Viet wrote:
    >
    > my ($var1,$var2) = @{%$h}{@list};

    -----------------------^

    What is that % character supposed to do? It was not there in your
    initial post.

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
     
    Gunnar Hjalmarsson, Feb 23, 2009
    #8
  9. Patrick Viet

    Marc Lucksch Guest

    Patrick Viet schrieb:
    > my @list = qw(a b);
    >
    > my ($var1,$var2) = @{%$h}{@list};

    Well, there is you problem right there, because in your first post you
    wrote:
    > @{$h}{@list}

    and here you wrote:
    > @{%$h}{@list};

    Which is a different thing. scalar %$h gives you the bucket information
    (3/8) in your case, means: 3 of 8 buckets are filled.

    Quote man perldata:

    > If you evaluate a hash in scalar context, it returns false if the hash
    > is empty. If there are any key/value pairs, it returns true; more
    > precisely, the value returned is a string consisting of the number of
    > used buckets and the number of allocated buckets, separated by a
    > slash. This is pretty much useful only to find out whether Perl's
    > internal hashing algorithm is performing poorly on your data set. For
    > example, you stick 10,000 things in a hash, but evaluating %HASH in
    > scalar context reveals "1/16" , which means only one out of sixteen
    > buckets has been touched, and presumably contains all 10,000 of your
    > items. This isn't supposed to happen. If a tied hash is evaluated in
    > scalar context, a fatal error will result, since this bucket usage
    > information is currently not available for tied hashes.


    > --------------------
    > #!/usr/bin/perl
    >
    > use warnings;
    > use strict;
    >
    > my %h = (
    > a => 'test1',
    > b => 'test2',
    > c => 'test3',
    > );
    >
    > my @list = qw(a b);
    >
    > my ($var1,$var2) = @{\%h}{@list};


    You should better do this (no refrences needed):

    my ($var1,$var2) = @h{@list};

    Simple way to remember this:

    $h{a}: Scalar of %h
    %h: Hash %h
    @h{@ab} = array from %h of the keys in @ab.

    Marc "maluku" Lucksch
     
    Marc Lucksch, Feb 23, 2009
    #9
  10. Patrick Viet

    Tim McDaniel Guest

    In article <gnv0u7$1d8u$-clausthal.de>,
    Marc Lucksch <> wrote:
    >Patrick Viet schrieb:
    >> --------------------
    >> #!/usr/bin/perl
    >>
    >> use warnings;
    >> use strict;
    >>
    >> my %h = (
    >> a => 'test1',
    >> b => 'test2',
    >> c => 'test3',
    >> );
    >>
    >> my @list = qw(a b);
    >>
    >> my ($var1,$var2) = @{\%h}{@list};

    >
    >You should better do this (no refrences needed):
    >
    >my ($var1,$var2) = @h{@list};


    Note that Marc changed the quoted code but left it quoted and with
    Viet's attribution. The original had
    my $h = { ... };
    but the new version above has
    my %h = ( ... );

    That is, Marc changed it from a scalar variable that contained a
    reference to a hash - to a hash variable that contained, well, a hash.

    I agree that that using a hash, instead of a reference to a hash, is
    better is in this kind of case. I just wanted to point out that
    goalposts were being moved silently.

    --
    Tim McDaniel,
     
    Tim McDaniel, Feb 23, 2009
    #10
  11. Patrick Viet

    Tim McDaniel Guest

    In article <gnv0c9$3o9$-com.hr>, Matija Papec <> wrote:
    >Patrick Viet wrote:
    >
    >> my ($var1,$var2) = @{\%h}{@list};

    >
    >less crappy version:
    >my ($var1,$var2) = @h{@list};


    Please test your code before making suggestions. With the original
    my $h = {
    a => 'test1',
    b => 'test2',
    c => 'test3',
    };
    the "less crappy" version (under perl -w and use strict) gives
    Global symbol "%h" requires explicit package name at
    local/test/051.pl line 15.
    Execution of local/test/051.pl aborted due to compilation errors.

    As Marc (silently) noted, you have to change the assignment from
    $h = {...} to %h = (...).

    --
    Tim McDaniel,
     
    Tim McDaniel, Feb 23, 2009
    #11
  12. Patrick Viet

    Tim McDaniel Guest

    In article <gnv0u7$1d8u$-clausthal.de>,
    Marc Lucksch <> wrote:
    >Patrick Viet schrieb:
    >> my @list = qw(a b);
    >>
    >> my ($var1,$var2) = @{%$h}{@list};

    >Well, there is you problem right there, because in your first post you
    >wrote:
    > > @{$h}{@list}

    >and here you wrote:
    > > @{%$h}{@list};

    >Which is a different thing. scalar %$h gives you the bucket information
    >(3/8) in your case, means: 3 of 8 buckets are filled.


    To expand on that: in, @{EXPR}{list} (for whatever happens to be
    "EXPR" in any particular case), the syntax requires that EXPR be a
    reference to a hash, or be the bare name of a hash variable itself.
    If EXPR is indeed an expression, like %$h, it is evaluated, so far as
    I can tell, in a scalar context. As Marc noted, that gives you a
    string that tells you information about the hash table (here, that
    there are 3 elements and 8 buckets, I think, but I can't find it
    quickly in the man pages).

    In Perl 5.10, and I suspect in many earlier versions, you can use
    either
    @{$h}{@list}
    or
    @$h{@list}

    But, as Marc noted, using a real hash variableis better in this case,
    avoiding the extra $ in lots of cases.

    --
    Tim McDaniel,
     
    Tim McDaniel, Feb 23, 2009
    #12
  13. Tim McDaniel wrote:
    > But, as Marc noted, using a real hash variableis better in this case,
    > avoiding the extra $ in lots of cases.


    I'm not sure that Marc noted that. Besides, considering that the OP's
    real code is:

    while(my $href = $sth->fetchrow_hashref) {
    my $key = join('|',@{$href}{@cols_primary});

    I'm somewhat confused by your advice.

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
     
    Gunnar Hjalmarsson, Feb 23, 2009
    #13
  14. Patrick Viet

    Marc Lucksch Guest

    Gunnar Hjalmarsson schrieb:
    > Tim McDaniel wrote:
    >> But, as Marc noted, using a real hash variableis better in this case,
    >> avoiding the extra $ in lots of cases.

    >
    > I'm not sure that Marc noted that. Besides, considering that the OP's
    > real code is:
    >
    > while(my $href = $sth->fetchrow_hashref) {
    > my $key = join('|',@{$href}{@cols_primary});
    >


    I was in fact talking about his other post where he wrote:

    > Other script that produces the same result without hash ref :
    > use warnings;
    > use strict;
    >
    > my %h = (
    > a => 'test1',
    > b => 'test2',
    > c => 'test3',
    > );
    >
    > my @list = qw(a b);
    >
    > my ($var1,$var2) = @{\%h}{@list};
    >
    > print "var1 : $var1 $var2\n";


    Marc "Maluku" Lucksch



    =begin OffTopic

    And about this code:
    > while(my $href = $sth->fetchrow_hashref) {
    > my $key = join('|',@{$href}{@cols_primary});


    I think the OP wants to build kind of a primary key out of some combined
    values of the row. (Just a wild guess)
    Any database I know can use combined columns as keys (also primary keys)
    so I think that this code is quite useless with a good database design.

    =end OffTopic

    =cut
     
    Marc Lucksch, Feb 23, 2009
    #14
  15. On 2009-02-23 20:48, Tim McDaniel <> wrote:
    > In article <gnv0c9$3o9$-com.hr>, Matija Papec <> wrote:
    >>Patrick Viet wrote:
    >>
    >>> my ($var1,$var2) = @{\%h}{@list};

    >>
    >>less crappy version:
    >>my ($var1,$var2) = @h{@list};

    >
    > Please test your code before making suggestions. With the original
    > my $h = {
    > a => 'test1',
    > b => 'test2',
    > c => 'test3',
    > };


    That isn't the original in this case. It's:

    my %h = (
    a => 'test1',
    b => 'test2',
    c => 'test3',
    );

    > As Marc (silently) noted, you have to change the assignment from
    > $h = {...} to %h = (...).
    >


    Patrick already did this in the posting Matija replied to.

    hp
     
    Peter J. Holzer, Feb 23, 2009
    #15
  16. Tim McDaniel <> wrote:

    > If EXPR is indeed an expression, like %$h, it is evaluated, so far as
    > I can tell, in a scalar context. As Marc noted, that gives you a
    > string that tells you information about the hash table (here, that
    > there are 3 elements and 8 buckets, I think, but I can't find it
    > quickly in the man pages).



    It is in the "Scalar values" section of perldata.pod:

    If you evaluate a hash in scalar context, it returns false if the
    hash is empty. If there are any key/value pairs, it returns true;
    more precisely, the value returned is a string consisting of the
    number of used buckets and the number of allocated buckets, separated
    by a slash.


    --
    Tad McClellan
    email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"
     
    Tad J McClellan, Feb 23, 2009
    #16
    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. le Cl?
    Replies:
    15
    Views:
    3,174
    Michel
    Apr 11, 2009
  2. =?Utf-8?B?Z2xlbm4=?=

    Pseudo code to update Access db using VB.NET

    =?Utf-8?B?Z2xlbm4=?=, Apr 4, 2006, in forum: ASP .Net
    Replies:
    1
    Views:
    2,557
    =?Utf-8?B?UGhpbGxpcCBXaWxsaWFtcw==?=
    Apr 4, 2006
  3. rp
    Replies:
    1
    Views:
    562
    red floyd
    Nov 10, 2011
  4. Srijayanth Sridhar
    Replies:
    19
    Views:
    656
    David A. Black
    Jul 2, 2008
  5. Replies:
    3
    Views:
    227
Loading...

Share This Page