Re: Examining the existence of a hash key instantiates higher level keys

Discussion in 'Perl Misc' started by Rainer Weikusat, Dec 19, 2012.

  1. Ben Morrow <> writes:
    > Quoth Henry Law <>:
    >> I'm sure this is working as designed but it caught me out so I'm posting
    >> here in the hopes that they next guy who wears out his keyboard trying
    >> to find the source of this error will find it!


    [...]

    >> In other words, examining the existence of a subkey of a key that
    >> doesn't itself exist calls the higher level key into being.

    >
    > Writing a multi-level exists isn't hard:
    >
    > use Scalar::Util qw/reftype/;
    > use Carp qw/croak/;
    >
    > sub mexists {
    > my $href = shift;
    > while (my $key = shift) {
    > ref $href and reftype $href eq "HASH"
    > or croak "Not a HASH reference";


    According to the documentation, reftype returns the 'reference type'
    if the argument is a reference or undef otherwise. Consequently, the
    value of

    ref($href) and reftype($href) eq 'HASH'

    is identical to the value of

    reftype($href) eq 'HASH'
    Rainer Weikusat, Dec 19, 2012
    #1
    1. Advertising

  2. Rainer Weikusat

    Hans Mulder Guest

    Re: Examining the existence of a hash key instantiates higher levelkeys

    On 19/12/12 13:54:15, Rainer Weikusat wrote:
    > According to the documentation, reftype returns the 'reference type'
    > if the argument is a reference or undef otherwise. Consequently, the
    > value of
    >
    > ref($href) and reftype($href) eq 'HASH'
    >
    > is identical to the value of
    >
    > reftype($href) eq 'HASH'


    The two expressions have different results when you've done:

    $href = bless {}, 0;

    But then, you shouldn't do that.


    -- HansM
    Hans Mulder, Dec 19, 2012
    #2
    1. Advertising

  3. Hans Mulder <> writes:
    > On 19/12/12 13:54:15, Rainer Weikusat wrote:
    >> According to the documentation, reftype returns the 'reference type'
    >> if the argument is a reference or undef otherwise. Consequently, the
    >> value of
    >>
    >> ref($href) and reftype($href) eq 'HASH'
    >>
    >> is identical to the value of
    >>
    >> reftype($href) eq 'HASH'

    >
    > The two expressions have different results when you've done:
    >
    > $href = bless {}, 0;
    >
    > But then, you shouldn't do that.


    The documentation to bless demands 'Make sure that CLASSNAME is a true
    value', IOW, this is an instance of "you must not do that" not "you
    shouldn't do that". In the given context, however, this jus means the
    original code is not only clumsy but can also be considered broken: It
    will descend into objects except if these objects were blessed into a
    'class' whose name is equivalent to 'a false value' and insofar this
    check is sensible at all, it should be

    ref($href) eq 'HASH'

    and the original code should really have been (provided descending
    into objects whose implementation happens to be an anonymous hash was
    actually desired)

    ref($href) ne '' and reftype($href) eq 'HASH'
    Rainer Weikusat, Dec 19, 2012
    #3
  4. Ben Morrow <> writes:
    > Quoth Rainer Weikusat <>:
    >> Ben Morrow <> writes:
    >> > Quoth Henry Law <>:
    >> >> I'm sure this is working as designed but it caught me out so I'm posting
    >> >> here in the hopes that they next guy who wears out his keyboard trying
    >> >> to find the source of this error will find it!

    >>
    >> [...]
    >>
    >> >> In other words, examining the existence of a subkey of a key that
    >> >> doesn't itself exist calls the higher level key into being.
    >> >
    >> > Writing a multi-level exists isn't hard:
    >> >
    >> > use Scalar::Util qw/reftype/;
    >> > use Carp qw/croak/;
    >> >
    >> > sub mexists {
    >> > my $href = shift;
    >> > while (my $key = shift) {
    >> > ref $href and reftype $href eq "HASH"
    >> > or croak "Not a HASH reference";

    >>
    >> According to the documentation, reftype returns the 'reference type'
    >> if the argument is a reference or undef otherwise. Consequently, the
    >> value of
    >>
    >> ref($href) and reftype($href) eq 'HASH'
    >>
    >> is identical to the value of
    >>
    >> reftype($href) eq 'HASH'

    >
    > The latter produces an 'undef' warning if $href is not a ref.


    As somebody else pointed out: It is possible to bless a reference into
    class 0 and in this case, ref will return false (0, to be
    precise). And (as I wrote elsewhere), descending into objects whose
    implementation happens to be a hash looks like a rather quirky
    'feature' to me. Using

    ref($href) eq 'HASH'

    avoids both problems (descending into objects and the "Possibly
    erroneous conversion detected ! Panic in the streets !!" diagnostic).
    Rainer Weikusat, Dec 19, 2012
    #4
  5. Ben Morrow <> writes:
    > Quoth Rainer Weikusat <>:
    >> Ben Morrow <> writes:
    >> > Quoth Rainer Weikusat <>:


    [...]

    >> >>
    >> >> reftype($href) eq 'HASH'
    >> >


    [...]

    >> ref($href) eq 'HASH'
    >>
    >> avoids both problems (descending into objects and the "Possibly
    >> erroneous conversion detected ! Panic in the streets !!" diagnostic).

    >
    > ...but introduces the new problem of objects blessed into the class
    > "HASH", and leaves the (as yet unaddressed) problem of objects which may
    > or may not be implemented as a hashref but which have an overloaded
    > %{}.
    >
    > Type-checking in Perl is unfortunately not the least bit easy; anyone
    > concerned about doing it properly should use


    [the usual suggestion that the solution to any problem is "download
    more stuff form the internet"]

    Personally, I would omit the check and use something like

    sub mexists($@)
    {
    my $cur;

    $cur = shift;
    for (@_) {
    exists($cur->{$_}) or return;
    $cur = $cur->{$_};
    }

    return 1;
    }

    and in case I had to deal with input values where this wouldn't work,
    I would either extend it to cover these cases as well or get rid of
    the 'annoying' inputs, whatever seemed more feasible. In certain
    cases, eg the 0 and HASH 'classes', when people are purposely
    disregarding recommendations/ requirements in the documentation, they
    start to deserve whatever might be hitting them because of that. It
    should also be relatively easy to circumvent even the most
    sophisticated 'perl argument valdiation system' by runtime-linking
    suitable C code into the interpreter, meaning, intentional (or even
    accidental) sabotage is always an option.

    "It would prefer that you stayed out of its living room because you
    weren't invited, not because it has a shotgun."
    Rainer Weikusat, Dec 19, 2012
    #5
  6. Rainer Weikusat <> writes:

    [...]

    > Personally, I would omit the check and use something like
    >
    > sub mexists($@)
    > {
    > my $cur;
    >
    > $cur = shift;
    > for (@_) {
    > exists($cur->{$_}) or return;
    > $cur = $cur->{$_};
    > }
    >
    > return 1;
    > }
    >
    > and in case I had to deal with input values where this wouldn't work,
    > I would either extend it to cover these cases as well or get rid of
    > the 'annoying' inputs, whatever seemed more feasible.


    Slight alteration: Since the 'object stored in a hash' case is rather
    common, I'd probably make that

    use Scalar::Util qw(blessed);

    sub mexists($@)
    {
    my $cur;

    $cur = shift;
    for (@_) {
    !blessed($cur) and exists($cur->{$_}) or return;
    $cur = $cur->{$_};
    }

    return 1;
    }

    instead, at least after thinking about it for some time.
    Rainer Weikusat, Dec 19, 2012
    #6
    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. pabbu
    Replies:
    8
    Views:
    699
    Marc Boyer
    Nov 7, 2005
  2. rp
    Replies:
    1
    Views:
    477
    red floyd
    Nov 10, 2011
  3. Une bévue
    Replies:
    5
    Views:
    136
    Une bévue
    Aug 10, 2006
  4. Tim McDaniel

    Hash key types and equality of hash keys

    Tim McDaniel, Mar 1, 2012, in forum: Perl Misc
    Replies:
    2
    Views:
    772
    Tim McDaniel
    Mar 1, 2012
  5. Matt Hicks
    Replies:
    7
    Views:
    213
    Peter J. Holzer
    Dec 23, 2012
Loading...

Share This Page