Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Re^3: RFC: DBIx::Iterator

by chromatic (Archbishop)
on May 12, 2007 at 06:09 UTC ( [id://615044]=note: print w/replies, xml ) Need Help??


in reply to Re^2: RFC: DBIx::Iterator
in thread RFC: DBIx::Iterator

My best suggestion is to accept only one type of argument so you don't have to perform the check at all.

If that's not feasable, I suggest to dereference the reference appropriately inside an eval block. Otherwise you end up with a huge chain of tests just so that you don't miss all of the possibilities (non-reference, reference of the wrong type, reference of the right type, blessed reference, tied object, blessed reference of the wrong type with overloading, blessed reference of the right type with overloading).

Philosophically speaking, using UNIVERSAL::isa() to check for structural typing in Perl is perilous because Perl uses a nominal typing system (or behavioral, but no one ever talks about that). Sometimes the only way to know if you can do a thing is to do it and see if anything breaks.

Replies are listed 'Best First'.
Re^4: RFC: DBIx::Iterator
by runrig (Abbot) on May 12, 2007 at 16:16 UTC
    I could change all of the arguments to hash refs, but that would make using the function much more inconvenient. So, something like this as a check maybe?:
    my $href = { a => 1, b => 2 }; my $scalar = 4; no warnings 'void'; if ( eval { %$href; 1 } ) { print "href is a href\n"; } if ( eval { %$scalar; 1 } ) { # This had better not print print "scalar is a href\n"; }

      Yes, that's the simplest and most reliable solution I've found to date.

      One slight problem, in v5.8.8 (ActiveState build 820), this reports that the array reference is a hash reference:
      use strict; use warnings; my $aref = [qw(1 2 3 4)]; if ( eval { %$aref; 1 } ) { print "aref is a href\n"; my %hash = %$aref; }
      But it dies with Can't coerce array into hash when you try to dereference it outside of the eval. In 5.6.1, it does not report that the array ref is a hash ref. This seems to fix it:
      if ( eval { my $foo = %$aref; 1 } ) { print "aref is a href\n"; my %hash = %$aref; }
      In other code similar to the first instance ( but not that particular code for some reason), I did get the warning:
      Pseudo-hashes are deprecated
      which explains why an array reference could be considered a hash reference.

      Update: What I've ended up using is this:

      sub isa_hash { no warnings 'void'; my $hsh = shift(); return if eval { @$hsh; 1 }; return 1 if eval { %$hsh; 1 }; return; } sub isa_array { no warnings 'void'; my $arr = shift(); return 1 if eval { @$arr; 1 }; return; }
      UNIVERSAL::isa() is looking simpler all the time (even if wrong in obscure instances).

      Another Update: Borrowed from diotalevi's use perl journal:

      if ( eval { 1 + %$possible_href } ) { return 1; }

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://615044]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (3)
As of 2024-03-29 05:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found