Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

use fields; # damnit

by nothingmuch (Priest)
on Aug 20, 2004 at 20:39 UTC ( #384688=perlmeditation: print w/ replies, xml ) Need Help??

Howdy.

Every time I bring this up people say I'm bonkers. Here goes.

Occasionally Perl's OO system is bashed, because it's too lax, which is true in some respects. I guess the most sensible answer is "wait for Perl 6", or "use Java" for most arguments. That's what I hear, more often than not.

What I'm bringing up is one aspect of strictish OO that is handled in Perl. This is compile time field (properties, instance data) checking. What? compile time? Yes, fscking compile time, I'm not lying.

The fields pragma is, as far as I know, the least used useful module out there. This post is nothing but advocacy for it. Improperly used, it gives you no real benefits, except the implicit use of depracated features (pseudohashes), under Perl 5.8.

However, if you do all the steps you need to get the benefits, you end up with something pretty powerful, especially if you're a lousy typist, or can't read very well.

Say you are implementing a Dog. Some dogs are stupid. You might start out with something like this:

package Dog; sub new { my $pkg = shift; bless { intelligence => shift, }, $pkg; }
And then you add a method:
sub is_stupid { my $self = shift; return $self->{inteligence} < 3; }
Presto. You have a dog class. Now lets create $lassie. She is intelligent, right?
my $lassie = Dog->new(10); print "Lassie is " $lassie->is_stupid ? "dumb" : "smart";
Whoops. Warnings would help, but strict wouldn't. Anyway, you get the point. I typoed the field name, and everything broke. I could be pecking for hours, looking for that.

So lets get a little formal, and say what we define:

package Dog; use fields qw/intelligence/; sub new { my $pkg = shift; my $self = $pkg->fields::new(); $self->{intelligence} = shift; $self; }
So where does that get us? Well, nowhere. If you use base qw/Dog/ somewhere, the subclass would get that field, but that doesn't concern us now. Otherwise it's just a silly way to bless your $self.

The problem is that there's a general myth about fields, that that's all you're supposed to do, and that because it doesn't work, and to top it off uses pseudohashes, fields is bad. Both statements are false (the conclusion might not be, decide for yourself). Regarding the phashes, since 5.9 fields uses restricted hashes. The interface didn't change. In the future, fields might be implemented completely differently, and at the bottom line that's the point. You're not supposed to care that it uses phashes, because the phashes are hidden behind the usage interface.The other issue, well, we're getting there.

Lets move on to the my variable declaration. Notice that my TYPE $var syntax thingy? Well, it lets you tell perl that $var will be of class TYPE.

my Dog $lassie; # perl knows, at compile time, that lassie isa Dog
Aha! so If we do
package Dog; use fields qw/intelligence/; sub new { my $pkg = shift; my Dog $self = $pkg->fields::new; $self->{inteligence}; # typo again, but this time it doesn't compi +le $self; }
presto, we've got compile time field checking. If it were only a bit more concise, that could be really fun, but what does it matter. Go home and start using it.

</rant>

Update: grammer fixes.

-nuffin
zz zZ Z Z #!perl

Comment on use fields; # damnit
Select or Download Code
Re: use fields; # damnit
by NodeReaper (Curate) on Aug 20, 2004 at 20:44 UTC
    This node was taken out by the NodeReaper on Sat Aug 21 03:28:52 2004 (EST)
    Reason: gaal please delete: not-logged-in syndrome

    For more information on this node visit: this

Re: use fields; # damnit
by gaal (Parson) on Aug 20, 2004 at 20:47 UTC
    Yay! ++

    This obsoletes half my CPAN modules, but in a *good* way (who was it that said, you know you're improving your code when you delete portions from it?)

      (who was it that said, you know you're improving your code when you delete portions from it?)

      I remember that from Princepawn's sig.

      Carter's compass: I know I'm on the right track when by deleting something, I'm adding functionality

      --
      "A long habit of not thinking a thing wrong, gives it a superficial appearance of being right." -- Thomas Paine
      naChoZ

      You know you've achieved perfection in design, not when you have nothing more to add, but when you have nothing more to take away. -- Antoine de Saint Exupery
      That, perhaps?
        Ah, great quote (and great author!). I think I was vaguely recalling the quote naChoZ brought, but now that you mention it, this is probably the basis for that one.
Re: use fields; # damnit
by stvn (Monsignor) on Aug 20, 2004 at 21:38 UTC
    The problem is that there's a general myth about fields, that that's all you're supposed to do, and that because it doesn't work, and to top it off uses pseudohashes, fields is bad.

    My reason for not using fields has always been that in most of the books I was reading (Programming Perl 3rd Ed. and Damians book) would tell you about them and the 'Typed' my variables (and get my hopes up) and then tell you that they were built with pseudohashes which are an experimental feature and only to be used with caution, there might changes, etc. etc. etc. the usual warnings. Thus implying that use fields might also be a dangerous practice. I mean if it worked perfectly, more people would surely use this technique right? (at least that was my logic at the time).

    So I guess my question to you (and everyone else) is, are fields really ready for real world usage? Can I get these benifits today, without the risk of using "experimental" features?

    -stvn
      I use it in production code. The benefit is good enough for me that I will hold back an upgrade of Perl to keep using it, if needed.

      Either way, there's already patches for compile time support in 5.9 which does not use pseudohashes. If it gets merged (and it better), 5.10 should keep the same support, and i think that's a long time from now.

      At the bottom line, nobody in their right mind will take away this feature, especially from a languge whose motto is There Is More Than One Way To Do It. The worst I can foresee is that it might change a bit.

      -nuffin
      zz zZ Z Z #!perl

        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
      So I guess my question to you (and everyone else) is, are fields really ready for real world usage?

      Well, there are certainly people using it out there in the wild.

      That said, I don't and won't use them myself for three reasons.

      First, there are reasons why pseudo-hashes are being deprecated. Until the non-pseudo fields has been out for a couple of releases I'm not going to use them.

      Second, to use them we have to control the base-class. Often I'm coding in places where I don't control the base class. Since I like consistency throughout the code fields aren't that useful to me.

      Can I get these benifits today, without the risk of using "experimental" features?

      The third reason I don't use them is that I can get the benefit of compile-time field name typo checking (and other benefits too) by using Abigail's inside out objects technique - without having to touch any experimental features.

        First, there are reasons why pseudo-hashes are being deprecated. Until the non-pseudo fields has been out for a couple of releases I'm not going to use them.

        The point is that fields is guaranteed to keep working the way it does. That it uses pseudohashes is an implementation detail you are not supposed to care about.

        Of course, your objection that it requires knowledge about the implementation of the base class is valid and a good reason not to use it anyway.

        Makeshifts last the longest.

        Adrianh, I don't understand what you mean by "we have to control the base-class." I thought the fields pragma played well with inheritance. Could you give a concrete example where this would be a problem?

        ps, I just posted a followup to this thread at Should I use Fields, InsideOuts, or Properties?.

Re: use fields; # damnit
by Juerd (Abbot) on Aug 21, 2004 at 12:57 UTC

    My way of getting error messages when using the wrong property name is by using only the accessor methods. These are made lvalues, so they can be assigned to.

    use Attribute::Property; package Dog; sub new : New; sub intelligence : Property { /^\d+\z/ } package main; my $dog = Dog->new(intelligence => 15); $dog->intelligence++; my $dog = Dog->new(inteligence => 15); # error $dog->inteligence++; # error
    It saves a lot of typing (pun intended) too.

    Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

Re: use fields; # damnit
by ysth (Canon) on Aug 22, 2004 at 12:02 UTC
    See this p5p thread from 18 months ago for a description of some limitations of restricted-hash-based fields and some strong anti-compile-time-checking sentiment on the part of some (including rejection of a patch to put the checking back in bleadperl). types.pm, is unfortunately IMO uncommented to the point of unmaintainability.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://384688]
Approved by Corion
Front-paged by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (14)
As of 2014-12-18 17:33 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (59 votes), past polls