in reply to Re^2: Fields pragma - the poor man's OO framework?
in thread Fields pragma - the poor man's OO framework?

If you want static checks, don't use fields. Use something like Tie::Hash::FixedKeys.
use Tie::Hash::FixedKeys; my @keys = qw( a b c ); sub new { my $class = shift; my %args = @_; my $self = {}; tie %$self, 'Tie::Hash::FixedKeys', @keys; foreach my $k ( @keys ) { if ( exists $args{$k} ) { $self->{$k} = $args->{$k}; } } return bless $self, $class; }
Now, you have all the benefits of static fieldname checking without going into the depths of a deprecated feature. Maybe it's just me, but I'd strongly prefer that.

Of course, the better solution is to create your own OO framework that auto-generates mutators based on some static list of mutator names. Writing one is the matter of a couple hours. You can even crib heavily from CPAN and call it your own work. That way, everything is a method call. Direct attribute access is horrible practice.


My criteria for good software:
  1. Does it work?
  2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?

Replies are listed 'Best First'.
Re^4: Fields pragma - the poor man's OO framework?
by Arunbear (Prior) on Jul 07, 2008 at 10:07 UTC
    'static' in this context means 'checked at compile time' rather than 'restricted to a given set of values'.

    However if restriction to given values is wanted, I'd suggest Hash::Utils as it is core in 5.8 and above (and it does the restriction natively rather than using tie).

    package Foo; use strict; use Hash::Util qw( lock_keys ); my @attrs = qw( name alias race ); sub new { my $class = shift; my %args = @_; my $self = bless {}, $class; lock_keys(%$self, @attrs); foreach my $k ( @attrs ) { if ( exists $args{$k} ) { $self->{$k} = $args{$k}; } } return $self; } package main; my $c = Foo->new(name => 'Aragorn', alias => 'Strider', race => 'Human +'); print "name: $c->{name}\n"; print "job: $c->{job}\n";
    output:
    $ perl test.pl name: Aragorn Attempt to access disallowed key 'job' in a restricted hash at test.pl + line 26.
    As it happens, fields in 5.10 is implemented using Hash::Utils' restriction mechanism.
      You cannot check all hash accesses at compile time. Therefore, fields must do many things at runtime. Therefore, it must have a runtime component. I suggested using tie. lock_keys() is a perfectly good other solution. tie has the added benefit of being able to do other things than just restricting keynames. YMMV.

      My criteria for good software:
      1. Does it work?
      2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?

        As far as I can tell, 'fields' performs checks both at compile time (most common case, if used carefully) and at run-time (thanks to Hash::Util, as explained by Arunbear).

        I just noticed an issue (bug?) in the 5.10 implementation. I'll post it in a top-level subthread, so that any wandering Googler gets a chance to see it.