in reply to Re: Is "ref $date eq 'ARRAY'" wrong? What a mess!
in thread Is "ref $date eq 'ARRAY'" wrong?

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++.

  • Comment on Re: Re: Is "ref $date eq 'ARRAY'" wrong? What a mess!

Replies are listed 'Best First'.
Re: Re: Re: Is "ref $date eq 'ARRAY'" wrong? What a mess!
by stvn (Monsignor) on Dec 20, 2003 at 16:46 UTC

    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

      why do you think UNIVERSAL::isa returning ref type is a bad design (the perl developers obviously don't think so...)? using UNIVERSAL::isa to establish ref type allows one to turn the array ref that used to be passed to a method into a blessed object (preferably a tie in this case to intercept internal data access) that lists the fictitious class 'ARRAY' as a (completely abstract) superclass (or interface if you prefer).

      i do not think this is evidence of a bad design at all. it is just necessary to relax one's OO prejudices/convictions a little (which for perl OO, shouldn't be difficult ;-) ). on the contrary, i feel the 'ARRAY', 'HASH', etc pseudo classes ought to be used as marker interfaces (think java's Serialisable or Cloneable) to indicate the capability to be deferenced as a variable of that type (which, if the object supports a tie interface or has overloaded magic is really a method call in disguise). in other words, if isa( $thing, "ARRAY" ) returns true then $thing can be used as if it were a native array, regardless of exactly what $thing is, or how it implements array retrieval/storage. hooray for encapsulation *and* some nice parametric polymorphism as well.

      and FWIW, using isa() in this manner is used in quite number of cpan modules.

        Ok, I will give you credit that this is a very creative and elegant way to look at and use 'ARRAY', 'HASH', etc. But I think that co-opting the 'ARRAY' name is maybe not so good, for the simple reason that ref($thing) eq 'ARRAY' doesnt work. You have made the same word potentially mean 2 different thing in 2 different contexts. If you want a marker interface like Java, then why not just create one? Then your code can check for that interface explicitly, and you need never confuse your 'ARRAY' with Perl's 'ARRAY'. Also it seems to me that you are using UNIVERSAL (the Perl base class) as a module and not a class. You are mixing your paradigms here.

        Yes, you have your encapsulation and parametric polymorphism, but at what cost? IMHO you are violating the principle of least surprise, what I think is a duck, isnt really a duck, you would need to be pretty sure that it quacks exactly like a duck or your well laid plans can come crumbling down. Otherwise you are making assumptions about the internals of the packages/objects you are passing your 'ARRAY' too (basically, what it does with your 'ARRAY') which then violates their encapsulation. This can get really messy when that client package/module is not written/maintained by you.

        Yes I know I am anal about my OO, and I know that Perl's OO is a wide open field. But IMHO it could use a little more consitency. TMTOWTDI can still apply even within a more constrained object model.

        why do you think UNIVERSAL::isa returning ref type is a bad design (the perl developers obviously don't think so...)?

        I actually dont agree with alot of things the Perl developers did. And one of those things is how references are handled. References are currently clunky, and IMHO clearly an afterthought layed upon the original language. Most high-level languages do not force you to deal with things like this, i tend to view it as a sort of high-level memory management, and IMHO a high-level language should insulate you from such things. From what I have read on Perl 6, they are planning to make referencing and dereferencing automatic, but still allow the @{...} syntax to force dereferencing when you need it. But hey, this is just my opion, take it or leave it.

        and FWIW, using isa() in this manner is used in quite number of cpan modules.

        If quite a number of CPAN modules jumped off the brooklyn bridge, would you? ;-)

        But seriously, I respect the elegance of your solution, I just dont agree with it. I myself spent several weeks debating if my class library should add some useful functions to UNIVERSAL, or to package those functions into small classes and use multiple inheritance. In the end, I decided to leave UNIVERSAL as it is, I just couldn't justify what i saw as "changing the language" just for my evil purposes.

        -stvn
Re: Re: Re: Is "ref $date eq 'ARRAY'" wrong? What a mess!
by gmpassos (Priest) on Dec 20, 2003 at 17:44 UTC
    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".

      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.

      it is poor form to mandate a specific class name for anything except establishing capability. to establish whether a thing can perform only 1 or 2 methods, UNIVERSAL::can( $thing, "doFoo") is more flexible than UNIVERSAL::isa( $thing, "Fooable") besides.

      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.
      try: grep -nr 'isa' /usr/lib/perl | grep -e 'ARRAY' -e 'HASH'

      HASH, ARRAY, etc are not internal object data, they are type names in the same way that an object's class name is a type. If i wished to replace all array refs in my code with objects of my shiny new sorted array class with its TIEARRAY interface, i could change only the calling method (to create the object instead of the array ref), put 'ARRAY' into @MySortedArray::ISA as a pseudo-class (read: interface or capability to act as an array), then any code which used UNIVERSAL::isa( $thing, 'ARRAY' ) to establish that $thing could be dereferenced as an array (through its tie interface) would continue to work unchanged, but code using ref( $thing ) eq 'ARRAY' would break and need recoding. and in my company's 170,000 line perl app, recoding hundreds of methods because of bad coding is A Bad Thing and a huge PITA.

Re: Re: Re: Is "ref $date eq 'ARRAY'" wrong? What a mess!
by d_i_r_t_y (Monk) on Dec 20, 2003 at 05:28 UTC
    damnit, forgot to login. :-$