develooper Front page | perl.perl5.porters | Postings from February 2017

Re: Should we consider locked hashes a failed experiment?

Thread Previous | Thread Next
From:
Dave Mitchell
Date:
February 1, 2017 16:52
Subject:
Re: Should we consider locked hashes a failed experiment?
Message ID:
20170201165213.GL8158@iabyn.com
On Mon, Jan 30, 2017 at 08:47:27PM +0100, demerphq wrote:
> On 30 January 2017 at 18:13, Dave Mitchell <davem@iabyn.com> wrote:
> > On Sat, Jan 28, 2017 at 03:31:48PM +0100, demerphq wrote:
> >> My experience with locked hashes is that as currently implemented they
> >> are nearly useless.
> >
> > Their main advantage (as exposed by 'use fields') is that they check,
> > at *compile* time, that you're not using an invalid key for an
> > object, which has always been a big elephant in the room as regards
> > Perl's idiosyncratic use of hashes as objects.
> >
> >     package Foo;
> >
> >     use fields qw(a b c);
> >
> >     sub new { bless { qw(a 1 b 2 c 3) } }
> >
> >     package main;
> >
> >     my Foo $Fr = Foo->new();
> >
> >     $Fr->{a} = 1; # ok
> >     $Fr->{d} = 1; # compile-time error
> >
> > I'm not sure what checking is done at run time.
> 
> As far as I can tell none of the behavior demonstrated by your code is
> implemented by restricted hashes; in fact your sub new{} overrode the
> use of Hash::Util::lock_keys() in the constructor in fields.pm so your
> code does not use restricted hashes at all.

Ah, my mistake. Using code more close to the example in fields.pm gives
code with both compile-time and runtime checking:

    package Foo;

    use fields qw(a b c);

    sub new {
        my Foo $self = shift;
        unless (ref $self) {
            $self = fields::new($self);
        }
        $self->{a} = 10;
        $self->{b} = 20;
        return $self;
    }


    package main;

    my Foo $Fr = Foo->new();

    #$Fr->{a} = 1; # ok
    #$Fr->{d} = 1; # compile-time error

    $k = 'c';
    $Fr->{$k} = 1; # ok
    $k = 'd';
    $Fr->{$k} = 1; # runtime error


> my Foo $foo= Foo->new();
> 
> in the wild. No doubt they do somewhere, but not in any code I have
> looked at.

http://grep.cpan.me/?q=my%5Cs%2B%5Cw%2B%5Cs%2B%5C%24%5Cw%2B%5Cs*%3D.*%5Cbnew%5Cb
, that is, my\s+\w+\s+\$\w+\s*=.*\bnew\b,
gives 39 distributions

> And if you omit the "Foo" from "my Foo" (an easy mistake
> IMO) then the compile time checks go away as well, and fields.pm
> becomes completely run-time.

But that doesn't remove the fact that fields.pm offers an advertised
facility for detecting the use of invalid field names in object hashes,
which has always been one of the big criticisms of perl's "use a hash
as an object" model.

If we remove that facility from the hash code, we break fields.pm.

> ps: Where can i read up on how this is working at an internals level?

The compile-time behaviour is in S_check_hash_fields_and_hekify() in op.c,
which handles the processing of constant keys in hash lookups.

-- 
This is a great day for France!
    -- Nixon at Charles De Gaulle's funeral

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About