Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Is "ref $date eq 'ARRAY'" wrong?

by bronto (Priest)
on Dec 19, 2003 at 14:59 UTC ( [id://315807]=perlquestion: print w/replies, xml ) Need Help??

bronto has asked for the wisdom of the Perl Monks concerning the following question:

Hello

I am discussing on module-authors@perl.org about a module I would like to put on CPAN.

A proposal was made to improve the interface of the module; the suggested patch was to add a piece of code like this:

$date = ref $date eq 'ARRAY' ? $date : [ split(/\D+/, $date) ];

But another one said:

Never use the value of ref() except in a true/false test.

The correct way to tell if something is an array ref is

    ref $date && UNIVERSAL::isa($date, 'ARRAY')

Do you agree? And why?

Ciao!
--bronto


The very nature of Perl to be like natural language--inconsistant and full of dwim and special cases--makes it impossible to know it all without simply memorizing the documentation (which is not complete or totally correct anyway).
--John M. Dlugosz

Replies are listed 'Best First'.
Re: Is "ref $date eq 'ARRAY'" wrong?
by Ovid (Cardinal) on Dec 19, 2003 at 16:54 UTC

    Update: Changed the foreach push to a simple push. I will now lay down the crack pipe and step away from the keyboard.

    Using ref is quite frequently an indication of a design flaw. The higher level the code you're writing, the less likely it is that you'll want to use it. Here's an example that could cause a problem:

    my $foo = some_func(); if ('ARRAY' eq ref $foo) { push @data => @$foo; } else { push @data => $foo; }

    That's bug prone. Instead, it might be cleaner if some_func() always returned an array ref. If that's the case, the above code becomes:

    my $foo = some_func(); push @data => @$foo;

    The code becomes easier to read and understand as a result.

    If we're talking about what a function might accept, though, I'm a bit less stringent, but it's still easy to write bugs.

    sub some_func { my $self = shift; my @data = 'ARRAY' eq ref $_[0] ? @$_[0] : @_; # do stuff }

    On the surface, it looks like some_funct() can take an array, a list, or an array reference, and still behaves the same, regardless. However, what happens if some tries to pass in a list where the first element is also an array ref? Program fall down and go boom.

    In short, I don't disagree with using ref. Further, it might be appropriate for your program but I can't really say as I don't know what you are doing. However, any time you see someone using ref, you should look very carefully at their program to see if bugs are crawling around in there.

    Cheers,
    Ovid

    New address of my CGI Course.

      You couldn't possibly mean push @ary => $_! I mean, I understand using the fat arrow in some cases but you've got it pointing the wrong way. Since the arrow goes the wrong way, why aren't you using a plain comma?

        I can't make a serious justification, other than to visually group parts of an expression.

        push @array => $foo, $bar, $baz; join '|' => $foo, $bar, $baz; map func($_) => $foo, $bar, $baz;

        In this case, while the arrow appears reversed, I do it for stylistic consistency with the other expressions.

        Cheers,
        Ovid

        New address of my CGI Course.

        You couldn't possibly mean push @ary => $_!

        No, he actually meant push @ary, @$foo; rather than looping at all ;-)

Re: Is "ref $date eq 'ARRAY'" wrong?
by diotalevi (Canon) on Dec 19, 2003 at 15:24 UTC

    In the years since I've written this, UNIVERSAL::isa has been written. Use that instead.


    No, you'd have to say it as isa( $date, 'ARRAY' ). The documentation for UNIVERSAL says to import isa() before using it so here's the proper way. By using isa() you've just allowed your users to bless their arrays before giving them to you. When you check ref() you impose a no-blessings and no-subclassing requirement which really isn't all that friendly or perlish.

    *isa = \&UNIVERSAL::isa; sub foo { my $date = shift; return unless isa( $date, 'ARRAY' ); bar( $date ); }
      By using isa() you've just allowed your users to bless their arrays before giving them to you.
      Is that a good thing? You are suddenly going to accept object and depend on its internals. Not touching the internals of foreign objects (what the original code is doing) is IMO a good thing.

      Abigail

        Sure it is. You advertised that you accept array references it shouldn't matter to you what someone else thinks of that array. If someone else has an object and they think that its fine for someone else to treat their object as a plain array then it isn't a problem for the isa-using function author to do so.
      When you check ref() you impose a no-blessings and no-subclassing requirement which really isn't all that friendly or perlish.

      I don't agree.

      First off, you don't really "impose a no-blessings and no-subclassing requirement"; you just decide that you won't be responsible for it. There is nothing preventing a user of your code from writing something like

      my $original_package = ref $object; bless $object, 'ARRAY'; call_sub_that_expects_array_ref( $object ); bless $object, $original_package;

      I think it's probably more prudent to let your user take responsibility for treating his $object like an array reference. You can be permissive, but you might make it hard to catch some subtle bugs and you may be encouraging maintenance problems. Besides, the practical benefits are likely to be very few.

      Edit: Minor grammatical fixes.

      -sauoq
      "My two cents aren't worth a dime.";
      
        I have never before considered that blessing into ARRAY, HASH, and friends were anything outside of a pathological case. I mean, are you suggesting that someone should say that just to be depantic (which I'll understand) or that it is actually reasonable?
      Actually, if you read the docs carefully, they say if you really want to use a local function (merely to save yourself some typing?), then you can alias it as you describe (since you can't import it using Exporter).

      However, it's perfectly acceptable to call it as UNIVERSAL::isa. It's not necessary to do that aliasing stuff.

      ~J

Re: Is "ref $date eq 'ARRAY'" wrong?
by duff (Parson) on Dec 19, 2003 at 15:13 UTC

    I don't know that I necesarily agree, but one advantage of UNIVERSAL::isa is that it walks the inheritance tree for you. Which is probably useless for ARRAY, SCALAR, etc. refs. It all depends on what you know about your data :)

Re: Is "ref $date eq 'ARRAY'" wrong?
by ysth (Canon) on Dec 19, 2003 at 16:03 UTC
    If at all possible, its best to avoid either way: make the caller provide an array ref every time. That allows $date to be a blessed object whose underlying type is a hash but which has overloaded @{} array-dereference.

    No matter how you code the decision, there is some ambiguity. The caller could be passing an array-based object yet intending that the split be done using the object's overloaded stringify, for instance.

    In a sense, if you are checking UNIVERSAL::isa and then treating it as a plain array ref, you are voilating the object's encapsulation. Why should the underlying type matter to you? Conversely, it is often convenient for an object method to be able to pass the object if it were just an array ref.

    To sum it all up, you are guessing the caller's intent, and anything that involves a guess should preferably be avoided.

Re: Is "ref $date eq 'ARRAY'" wrong?
by hardburn (Abbot) on Dec 19, 2003 at 16:32 UTC

    If you're talking in terms of objects, then using ref is incorrect. However, if you know the data you're passing around isn't going to be blessed, ref is just fine.

    It'd be very nice if we had proper subroutine signatures, in which case the need for ref and isa would almost disappear. /me waits for Perl6.

    ----
    I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
    -- Schemer

    : () { :|:& };:

    Note: All code is untested, unless otherwise stated

Why ref() is bad.
by dragonchild (Archbishop) on Dec 19, 2003 at 17:38 UTC
    Figure out another way. Really. Like, it's ridiculous that ref is still being used in high-level code. And, I've got a really good reason.

    I have the following situation:

    • I have a baseclass that creates objects as arrayrefs.
    • I have a class that pretends to be a number, except when stringified, when it formats itself appropriately.
    • I use HTML::Template for display purposes.

    So far, so good, right? The problem is in the <readmore>

    Figure out another way. Use class names and provide a factory, use different function name to provide different signatures, anything! Just don't use ref!

    ------
    We are the carpenters and bricklayers of the Information Age.

    Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

      An alternative viewpoint is that HTML::Template was written to accept a scalar or an arrayref and deal with these appropriately. By overloading your object (array) references to act as scalars in a scalar context, and then passing these to HTML::Template, you are creating the problem and asking for pre-existing code to fix it.

      Couldn't you be the one to provide a separate function, $obj->toString(), and use that rather than overloading to pass the stringified value of your object to HTML::Template?

      ( Also, would $template->function( scalar $obj_to_stringify ); 'fix the problem'? ).

      Note: I'm playing devil's advocate here because this is one of those issues about which I am undecided.

      Not using ref, or context sensitivity in code seems like were throwing away a fundamental part of what makes perl, perl.

      On the other hand, maybe the dwimery that makes writing small, procedural code in perl such a pleasure, is simply at odds with writing larger, more complicates app where OO comes into it's own?


      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "Think for yourself!" - Abigail
      Hooray!

        You're absolutely correct, in that the code is documented as to what it does. However, there is a disconnect between the idea of an array reference and an object which just so happens to be implemented as an array reference.

        ... reads what he just wrote ...

        SIGH

        As a Perl hacker, I have problems with the twit who wrote the first part of this reply. I can easily see someone wanting to do something like:

        package My::Overloaded::Array; use overload '+=' => 'my_push'; sub my_push { my $self = shift; push @{$self}, @_; }

        Now, the hapless coder wants to have HTML::Template use it as an array. I have an object which is an arrayref and I want HTML::Template to treat it as a plain scalar that isn't a reference. And, frankly, there's no way for poor HTML::Template to tell the difference!

        ... thinks some more ...

        Unless our intrepid array-hacking hero overloads @{} (or whatever it's called these days ... []?) ... Or, I'm stuck with my solution of overriding isa(). What are your thoughts? (Maybe there's a meditation in all this rambling I seem to be doing of late ...)

        ------
        We are the carpenters and bricklayers of the Information Age.

        Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

      All because HTML::Template uses ref.

      Actually, no, that's not why. If it was just using ref() it wouldn't see that your object was an arrayref, it would see it as an object of some class. It uses isa(). This is exactly the advice the OP was getting: that he should use UNIVERSAL::isa(). I think that's generally poor advice and HTML::Template is one good example of one place just using ref() would have been an excellent idea.

      Here is the relevant crufty code from HTML::Template:

      if (defined($value_type) and length($value_type) and ($value_type +eq 'ARRAY' or ((ref($value) !~ /^(CODE)|(HASH)|(SCALAR)$/) and $value->isa('ARRA +Y')))) { (ref($param_map->{$param}) eq 'HTML::Template::LOOP') or croak("HTML::Template::param() : attempt to set parameter '$pa +ram' with an array ref - parameter is not a TMPL_LOOP!");

      I think you are really misplacing blame. You are using HTML::Template so, you've contracted to abide by its API. You can't expect HTML::Template to handle everyones quirky data, afterall. And I think that's the fundamental misconception here. It isn't the module author's responsibility to code for every contingency. It's his responsibility to develop an API that makes sense and stick to it. Keeping it simple is a sound approach!

      Your simple fix is to call

      $template->param( PARAM => "$object");
      In other words, stringify your object yourself. You're the one who knows it should be stringified. HTML::Template doesn't.

      -sauoq
      "My two cents aren't worth a dime.";
      
        Why is HTML::Template checking to see if I'm passing in an arrayref to a non-TMPL_LOOP param? Why should HTML::Template care?!? What if I wanted to see "ARRAY=(0x23453245)" as my value for some parameter. I can see a very good reason to do that - creating an online debugger. But, HTML::Template prevents me from doing that.

        Furthermore, HTML::Template doesn't check to see if the thing is truly a scalar. All it does is make sure the thing isn't an arrayref. The original version of my formatted number class used a hashref as its implementation. No problems. So, I figured that any implementation would work. And, in fact, any implementation would work ... except for arrayref. THAT is my complaint.

        Though, the fact that HTML::Template uses isa() makes sense, cause I "fixed" the problem by blocking isa() from reporting the object is any form of base type. You're right - ref wouldn't've caused the problem. I still stand why my statement - you shouldn't check to see if it is a duck ... you should check to see if it walks, talks, and smells like a duck. Deal with interface, not implementation. And, that can be done pretty simply.

        As for me knowing it should be stringified ... HTML::Template should trust me. If I say I want it to use X as a scalar, it should let me. It smacks too much of B&D, the way it does things now.

        ------
        We are the carpenters and bricklayers of the Information Age.

        Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

Re: Is "ref $date eq 'ARRAY'" wrong?
by runrig (Abbot) on Dec 19, 2003 at 19:53 UTC
Re: Is "ref $date eq 'ARRAY'" wrong?
by dada (Chaplain) on Dec 19, 2003 at 17:12 UTC
    maybe I'm totally out of track (it's been a long and hard week :-), but I would go with something like:
    $date = (ref $date =~ /ARRAY/) ? $date : [ split(/\D+/, $date) ];
    it is safe enough, I think, to treat the reference as an array if it "implements" an array (eg. if it's something like Foo::Bar=ARRAY(0xdeadbeef)) the same way it is safe enough to call $object->{property} when $object is something like Foo::Bar=HASH(0xdeadbeef).

    don't know, however (I don't have time to check now), if this works for tied arrays.

    someone correct me please if I'm wrong :-)

    cheers,
    Aldo

    King of Laziness, Wizard of Impatience, Lord of Hubris

      Humm, you are making 2 things wrong!

      Take a look in this code:

      package foo ; my $bless = bless({},foo); print "AS STRING: $bless\n" ; print "AS REF: ". ref($bless) ."\n" ; __END__ ## OUTPUT: AS STRING: foo=HASH(0x1a7f04c) AS REF: foo
      ref just return in what package the object is blessed or the data type of the reference. If you want to know if the blessed reference is an ARRAY, HASH, SCALAR... you can use:
      if ( UNIVERSAL::isa($bless , 'HASH') ) { print "mohhh\n" ; }
      And forget the REGEXP for that!

      Graciliano M. P.
      "Creativity is the expression of the liberty".

Re: Is "ref $date eq 'ARRAY'" wrong?
by stvn (Monsignor) on Dec 19, 2003 at 22:31 UTC

    I am not sure i agree with the comment about not using the value of ref().

    Granted there are many issues and complexities to the current implementation of references that make me cringe at times. But given that currently there are more than one "type" of reference available (blessed objects aside for a moment), I see ref() as a reasonable way to query that type (albeit somewhat ugly). Of course its use should be highly restricted and very well documented.

    Since Perl does not (yet) perform automatic dereferencing (like say Javascript which handles all the "is it a value, is it a ref" stuff for you). And the accessing of hash and array elements are done with different brackets (again, JS allows both to be accessed with the same square bracket syntax). I think that sometimes just knowing a variable is a reference is not enough.

    Now, as for usage, my feeling is that ref() should really only be used for checking subroutine arguments. This should always be very well documented, so that its obvious to the user of your module when and where they are allowed to use references. For instance I have a Collection class, which aims to provide a more OO array-like interface (sort of like the Java and Smalltalk collection classes). It can take either an plain perl array or an array reference. The array reference is more efficient (especially when that is what you have already) since it spares the overhead of passing several arguments and the creation of a new array to hold them. I avoid the problem brought up by Ovid (where the first element of a list is itself an array reference) by only allowing a single array reference to be passed:

    if (scalar @args == 1) { # .. got an array ref } else { # treat it as a plain array }

    I also do the same for my Dictionary class (a hash wrapper) with hash refs and hashes in the argument list.

    All other usages of ref() are suspect, but as always if you can justify your reasoning in a good comment, and make sure that you are not causing more problems than you are solving, by all means use it.

    All that ref() stuff said, I highly disagree with that usage of UNIVERSAL::isa.

    UNIVERSAL is Perl's attempt at a base object class, which like references is maybe not so good an implementation of it. But one of the fundemental base concepts of OO is that of encapsulation, and that usage (and the importation of isa as suggested in the documentation) violates that concept totally.

    As for all the thoughts about accepting other types of classes (some which might overload @{} or something similar), this should be detailed in the documentation, and handled approriately. Something like this could be possible.

    if (ref($date) =~ /^ARRAY$/) { # ... its an array ref } elsif (ref($date) =~ /ARRAY/) { # ... its an array based class } elsif (overload::Overloaded($date)) { # ... although not definitive, # its possible that @{} is overloaded # use this at your own risk } else { # its probably a string .... }

    Of course, I cannot stress documentation enough, it will clear up all the ambiguities of usage.

    -stvn
Re: Is "ref $date eq 'ARRAY'" wrong?
by Roy Johnson (Monsignor) on Dec 19, 2003 at 19:42 UTC
    Others have addressed the main question. I just wanted to comment that it always strikes me as clunky to assign something to itself. Useless use of the ternary operator, you might call it.

    Instead of A = test ? A : B, simply A = B unless test. Or test and A=B, if brevity is your thing. (Personally, I also favor and when I'm doing a sequence of steps vs. building a single expression with &&.)


    The PerlMonk tr/// Advocate
Re: Is "ref $date eq 'ARRAY'" wrong? What a mess!
by gmpassos (Priest) on Dec 20, 2003 at 03:09 UTC
    Ow my god! What a confusion that some monks are making here!

    First, doesn't exists the object type ARRAY or the package ARRAY, ok?!

    ref(), like the name tell, is just for reference type! Soo, if you make ref() you can have returned the reference for the data type, SCALAR, ARRAY, HASH, GLOB, CODE and REF.

    What we need to remember is that an object make a reference to a package, soo ref() also return the name of the package, or where this object is blessed. But the name of the package, let's say FOO, is something very different of the data types SCALAR, ARRAY, HASH, GLOB, CODE. Remember, ref() only take care about reference types!

    Soo, if some crazy people say to you to not use ref() to see if you have an ARRAY ref, or an normal SCALAR/string, forget! Actually, ref() was created to be used exactly in this case!

    About isa, you should use it for objects, and only for objects! UNIVERSAL, as POD say, is the base "class" for all the objects, since all of them "extends" UNIVERSAL, actually, all of them have UNIVERSAL at @ISA by default.

    Soo, this code is trying to know if you have an object that extends the package/class ARRAY, or if it has ARRAY in the @ISA tree, as the name say, isa():

    UNIVERSAL::isa($date, 'ARRAY')
    It will work for a reference too, but was not made for that! Soo, if some day some other crazy people make the module/class ARRAY, and than build another module that extends it, let's say ARRAY::EvenCrazy, isa($obj_array_crazy , 'ARRAY') will return true too!

    Now about ref() with objects, the only case that you should use it, is when you explicity want an object blessed in the package FOO, soo is rigth to write:

    if ( ref($obj) eq 'FOO' ) {...}

    Still on isa(). If you want to accept an object reference, and use it's internal type (ARRAY, HASH, CODE, GLOB) as a non blessed reference/data, you can use isa:

    if ( UNIVERSAL::isa($blessed_in_foo , 'HASH') ) { print "Is an HASH object!\n" ; }
    But I never saw that and I think that this is very wrong, specially in OO style, since you are accessing/changing it's internal structure/attributes directly, and not by methods!

    Note that be "paranoic" is the worst thing that you can make in your code. You will create a lot of bugs and make your code slow! You have to use what was created for, to be used for each need, this is how we create cool codes. ;-P

    Graciliano M. P.
    "Creativity is the expression of the liberty".

      from man perlobj:
             isa(CLASS)
                 "isa" returns true if its object is blessed into a subclass of
                 "CLASS"
      
                 You can also call "UNIVERSAL::isa" as a subroutine with two argu-
                 ments.  The first does not need to be an object or even a refer-
                 ence.  This allows you to check what a reference points to, or
                 whether something is a reference of a given type. Example
      
                     if(UNIVERSAL::isa($ref, 'ARRAY')) {
                         #...
                     }
      
                 To determine if a reference is a blessed object, you can write
      
                     print "It's an object\n" if UNIVERSAL::isa($val, 'UNIVERSAL');
      
      

      UNIVERSIAL::isa( $thing, "CLASS" ) is a far superior method than ref( $thing ) eq 'CLASS', since the latter does not cater for inheritance.

      But I never saw that and I think that this is very wrong, specially in OO style, since you are accessing/changing it's internal structure/attributes directly, and not by methods!

      try reading perldoc perlobj!
      calling UNIVERSAL::isa does not "access/change internal structure/attributes" -- it is the OO equivalent of a class/static method call in java or c++.

        But 'ARRAY' is not a class. When ref() returns 'ARRAY' it is describing the array reference (which is what the question was posed about). The fact that UNIVERSAL::isa returns 'ARRAY', IMHO, is a bad design. It should return undef instead, since 'ARRAY' is not a class, therefore it doesn't inherit from UNIVERSAL or have an @ISA associated with it.

        If one really wanted to argue this, it could be said that since you must bless a reference, that all references then are essentially base classes, but I have not seen anything in the Perl OO documentation to indicate this as an acceptable point of view. And this contradicts the idea of UNIVERSAL which is and does function as the Perl base class.

        Personally I do not like single inheritance, or the idea of deep inheritance heirarchies steming from a single base class. They are fragile and contradict the idea of encapsulation since sometimes one needs to navigate deep into a heirarchy to find a method implementation. Anyone who has navigated a javadoc will understand what i mean. I have always felt that multiple inheritance and class composition (through a variety of means) are far superior, along with the Eiffel idea of flattened class views (where the heirarchy is flattened for the documentation so that all methods are viewable as members of the top level class).

        And while you are correct that this does not truely reveal the internals of any object, the usage of UNIVERSAL with the double colon does subvert the OO syntax '->' and essentially turn UNIVERSAL into a plain vanilla Perl package/module. By subverting the '->' method call syntax you are bypassing the built in method resolution and essentially bypassing the inheritance heirarchy (which of course doesnt really matter since UNIVERSAL is the base class anyway).

        I dont agree either that this is equivalent to calling a class or static method. I dont see Perl as having true equivalents of static methods, and a class method (at least the way i view them) is a method you call through the class an not through the instance. In other words it doesnt require an instance to be called. But you should still call it with the '->' method invocation syntax.

        I think it should be kept in mind that an array reference (ARRAY) is not a class (or even blessed for that matter), and hence really shouldn't be treated as such (IMHO of course).

        -stvn
        As I said, ref() should be only used with objects if you really want, explicity, an object blessed in the class FOO, soo, without care about inheritance.

        > > But I never saw that ...
        > try reading perldoc perlobj!

        I know that this is possible, as I show in the previous node, what I said is that I never saw this in use! I never saw a code that want's to use the internal object data, HASH, ARRAY,... as a normal data! And I think, that shouldn't be used, since this is not a good thing when we are talking about OO.

        Graciliano M. P.
        "Creativity is the expression of the liberty".

        damnit, forgot to login. :-$
Re: Is "ref $date eq 'ARRAY'" wrong?
by dragonchild (Archbishop) on Dec 19, 2003 at 20:16 UTC
    How about this:
    sub normalize_date { my $date_proto = shift; my $stringified = "$date_proto"; # Check to see if it's NOT a reference unless ($stringified =~ /\(0[Xx]\d+\)$/) { return split /\D+/, $date_proto; } # At this point, we know we have a reference of some sort ... # Let's see if it acts as an array ... if ( eval { @{$date_proto}; 1} } ) { # We know we can treat $date_proto as an array return $date_proto; } # At this point, we don't know what to do with $date_proto. # (Well, the OP hasn't spec'ed it out ...) }

    The major update here is that it plays nicely with overload. For example, I might have:

    package Date::As::Hash; use overload '""' => 'stringify'; # Some stuff here ... sub stringify { my $self = shift; "$self->{MONTH}/$self->{DAY}/$self->{YEAR}"; }

    I wish HTML::Template would do something like this ...

    ------
    We are the carpenters and bricklayers of the Information Age.

    Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

Re: Is "ref $date eq 'ARRAY'" wrong?
by Sandy (Curate) on Dec 19, 2003 at 21:31 UTC
    I'm still relatively new to perl, so forgive the 'bad design' that everyone is talking about... but...

    I wrote an object that had a hash ref as part of the object properties (set via the $obj=new CLASS or $obj->Req_Trace(\%mytrace) method)
    * In order to ensure that I really had a hash (and not something else, 'case user made a mistake), I used something similar to this...

    my $self = shift; my %req = (); if (ref($self->Req_Trace()) eq "HASH") { %req = %{$self->Req_Trace()}; }

    Is this a case where using ref within an 'if' statement makes it ok?

    Is using @ISA supposed to be used here? If so, how?

    What don't I understand?

    Could someone explain it to me? (assume that I am not knowledgable about much).

    Thanks.

      It looks like you are using Req_Trace as a setter/getter, and that Req_Trace should only be set to a hash ref if set at all. In the above code, it looks like you are checking to see if its a hash ref after it's already been set, which IMO is the wrong place to be doing that. You should check to see if its a hash ref while it is being set, and in the above code, you would/may only need to check to see if it is set at all.

      That being said, to check to see if Req_Trace is passed a hash reference, some here would say to use UNIVERSAL::isa($rt_arg, 'HASH'), and some would say ref($rt_arg) eq 'HASH' is fine. Either way is 'broken' in one way or another:
      my $aref = [ 1..5 ]; bless $aref, 'HASH'; # An array ref now thinks it's a hash ref print "aref is a HASH\n" if ref($aref) eq 'HASH'; print "aref is a HASH\n" if UNIVERSAL::isa($aref, 'HASH'); my $href = { 0..9 }; # This is ok print "href is a hash\n" if ref($href) eq 'HASH'; bless $href, 'Some::Package'; # This may not be ok print "href is not a hash\n" unless ref($href) eq 'HASH';
      IMO, if you don't want to accept a blessed object which happens to be implemented as a hash ref (which is fine IMO), then ref is fine (I just want a hash ref, I don't want no damn stinkin' objects! :-) (update: oops, but it also accepts an object that thinks its a hash :). If you want to make absolutely sure that the argument passed is a hash reference, blessed or not, then you use Scalar::Util::reftype(). If you think people deserve what they get if they bless a non-hash reference into a 'HASH' package (I would lean this way also), then UNIVERSAL::isa is fine too.
        Thanks!

        And yeah, I know I should be checking if the has ref is a hash ref when it is being set, but I was new to OO and I used the examples in the camel book. In there, there is a nice example of creating methods on the fly.

        In retrospect, I would not have done it this way.

        So my way works only because this is the only place i actually use the hash, but at some future date if someone else adds to my module, it could possibly blow up.

        I'll fix it, I'll fix it... she whines...

A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://315807]
Approved by broquaint
Front-paged by gmax
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (4)
As of 2024-04-23 23:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found