Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Re^3: use fields; # damnit

by stvn (Monsignor)
on Aug 20, 2004 at 23:15 UTC ( #384728=note: print w/ replies, xml ) Need Help??


in reply to Re^2: use fields; # damnit
in thread use fields; # damnit

So, I am inspired, and I have been messing around with fields. But I am seeing some what seems to me to be odd behavior. (I am running perl 5.8.0 installed on Mac OS X, so maybe I need to update, if so, let me know.)

package Brain; use strict; use warnings; use fields qw/cells/; sub new { my $pkg = shift; my $self = $pkg->fields::new(); $self->{cells} = shift; $self; } package Dog; use strict; use warnings; use fields qw/intelligence/; sub new { my $pkg = shift; my $self = $pkg->fields::new(); my Brain $brain = Brain->new(shift); $self->{intelligence} = $brain; $self; } sub getBrain { my Dog $self = shift; return $self->{intelligence}; } package main; use strict; use warnings; my Dog $dog = Dog->new(10); my Dog $brain = $dog->getBrain(); my Brain $b = $brain;
This compiles and runs with no error or warning. Am I doing something wrong, or am I just assuming too much?

Sorry for this question, but my Programming Perl book does not go into too much detail (at least not that I have come across yet) and the Damian OO book is at the office (and I am not). And looking over the docs for fields it is not clear either.

-stvn


Comment on Re^3: use fields; # damnit
Download Code
Re^4: use fields; # damnit
by tilly (Archbishop) on Aug 21, 2004 at 00:09 UTC
    The syntax my Dog $brain declares that $brain is a Dog, and therefore everything that can be done with $brain has to be something that a Dog can do.

    These are compile-time tests on the container $brain.

    There is no runtime check in Perl 5 about whether the value put into $brain actually is a Dog. And the following line cannot be construed as a code error - after all nothing stops someone from making a class that inherits from both Dog and Brain!

      The syntax my Dog $brain declares that $brain is a Dog, and therefore everything that can be done with $brain has to be something that a Dog can do.

      But then how come this works without error? (assuming that the method getCells is declared in Brain)

      my Dog $brain = $dog->getBrain(); print $brain->getCells(); # prints 10 (see earlier example)
      Are you just speaking theoretically? Or are you just refering to class fields and not methods? If that is so, then where is the real benefit in this? It seems I have to write code like this, to see any benefit.
      print $brain->{cells}; # this prints: # No such pseudo-hash field "cells" in variable $brain of type Dog at +test.pl line 48.
      And to me that defeats so much of what makes OO good (yes I know I am being a purist, but hey, its my opinion).

      These are compile-time tests on the container $brain.

      There is no runtime check in Perl 5 about whether the value put into $brain actually is a Dog.

      So what is it checking then at compile time, if it cannot see the value I put in there and know its wrong? Is is only checking the underlying "hash" and access to that?

      after all nothing stops someone from making a class that inherits from both Dog and Brain!

      So it does not check the @ISA at all then either? Hmmm.

      Now I know that perl (like LISP, Python and others) is a more dynamic langauge than say Java, C# or even Ada95. And I know that to add something like "strong" typing would make much of what makes perl so cool just about impossible. But you don't need "strong" typing to get the benefits of type "safety". Type inference in Standard ML works just fine and IMO is superior to "strong" typing (and much simplier to use too). It seems to me that maybe fields and its accompanying technology is not finished yet, and if it is, then its not what I am looking for.

      -stvn
        The latter works without error because Perl 5 understands that the Dog method may have methods added later, and so does not assume that accessing a currently missing method is bad.

        In fact all that it understands are the fields of the object. So yes, it only checks hash access. And I agree with your comments about it not being very useful, which is why I personally don't bother with it.

        As for where this idea will go, not very far in Perl 5. In Perl 6 it may mutate into something more useful. But so far all that I can recall is lots of thought, but not much that is concrete.

        Incidentally I thought that type inference in Standard ML was a form of strong typing, but I don't know Standard ML. Since you appear to think otherwise, how would you describe the distinction that you'd draw?

        But then how come this works without error? (assuming that the method getCells is declared in Brain)

        What should happen if one of the classes has an AUTOLOAD? Also remember that you can add methods a class and remove them from it, at run time. You can even manipulate @ISA in all of your packages at runtime, completely changing your inheritance tree around at will. In fact, the inheritance tree is always manipulated on the fly, since there's no way to declaratively populate @ISA, even if that manipulation just so happens to commonly happen in implied BEGIN {} blocks.

        It is impossible to make your scenario fail properly at compile time because Perl is simply too dynamic. Other similarly dynamic very high level languages have similar problems with such scenarios.

        Makeshifts last the longest.

Re^4: use fields; # damnit
by nothingmuch (Priest) on Aug 21, 2004 at 09:08 UTC
    Field checking doesn't have much to do with accessors, or ISA checks. Reading the rest of your thread, I'd like to summarize.
    package Dog; use fields qw/intelligence/ sub new { my $pkg = shift; my Dog $self = $pkg->fields::new(); $self->{intelligence} = shift; $self; } sub intelligence { my Dog $self = shift; $self->{intelligence}; }
    That's the code you're responsible for. Lets say the accessor for 'intelligence' had a typo, and accessed the field 'inteligence'. Without using fields and typed variable declarations, you would not get any erros.

    This won't compile, and is broken:

    sub intelligence { my Dog $self = shift; $self->{inteligence}; # typo }

    And normally people would write

    sub intelligence { my $self = shift; $self->{inteligence}; # typo }
    and the code would compile correctly, but is just as broken.

    useing fields is meant to help you write your classes a bit cleaner, and is a bit like trying to catch typos in variable names. Just using $foo wouldn't work normally if there's no such variable, yet perl will only complain with use strict. Using a variable to store the intelligence value, $intelligence, and typoing it the next time around to $inteligence is the best analogy I can find for getting your field names wrong, and that's where use fields; helps.

    -nuffin
    zz zZ Z Z #!perl

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (17)
As of 2014-07-30 16:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (236 votes), past polls