develooper Front page | perl.perl5.porters | Postings from November 2001

Re: restricted hashes, and other readonlyness (was "clamp...")

Thread Previous | Thread Next
From:
Nick Ing-Simmons
Date:
November 1, 2001 09:13
Subject:
Re: restricted hashes, and other readonlyness (was "clamp...")
Message ID:
20011101171341.6376.9@bactrian.elixent.com
Jeffrey Friedl <jfriedl@yahoo.com> writes:
>Nick Ing-Simmons <nick.ing-simmons@elixent.com> wrote:
>|> Jeffrey Friedl <jfriedl@yahoo.com> writes:
>|> >Okay, I got rid of the union, the 'realkeys' stuff, added what was
>|> >needed for array readonlyness, and generally tidied up.
>|> >
>|> >I've dropped the "clamp" nomenclature, in favor of "pseudo-enumerated" or
>|> >"restricted" hashes.  (I still don't care what we call it, but I've got
>|> >to use something....)
>|>
>|> I think just "enumerated" will be fine - but see below.
>
>Okay, (and I still don't care what it's called), but FYI...
>
>   ...I thought that "pseudo-" would be useful for reminding people that
>   the list of enumerated keys can change at any time if someone
>   specifically goes to the trouble to unmark the hash, add/delete keys,
>   then remark it.

So we have re-enumerated them they are still enumerated - don't care to be
honest - just shorter name still made sense.

>
>|> >   Any access, other than exists(), with a key that is not approved results
>|> >   in an error.
>|>
>|>     I agree with Graham that exists on a non-approved key should also be
>|>     an error.
>
>Okay, not a big deal to me.
>
>|> >   A hash that is HvPSEUDO_ENUMERATED (and not SvREADONLY) may add and
>|> >   delete keys freely, but read access of a non-existant key is an
>|> >   error. This is a less restrictive form of a pseudo-enumerated hash
>|> >   that says "you can add elements freely, but if you're going to try
>|> >   to read an element, it had better actually be there."
>|>
>|>     Oh dear a 4th type which needs a name - say "Picky" :-(
>|>     With your sense of bits we now have:
>|>        RO EN
>|>        0   0   - normal
>|>        0   1   - "Picky"
>|>        1   0   - non-deletable Enumerated
>|>        1   1   - deletable Enumerated
>|>
>|> I can see some value in 'picky' hashes but I am sure we don't have
>|> concensus on them!
>
>Perhaps not, but wanting them was the original reasons I looked at this
>whole thing in the first place, and posted the first note on this topic
>back on July 19th.

;-)

>
>It's due to the discussions on p5p then, and now, that have resulted
>brought us to what we have today (which is, relatively speeking, fairly
>close to concensus.)

But we have not as far as I can tell discussed "picky" semantics since
the revival.

>
>|> As far as _I_ am concerned - I am convinced we need one of the "Enumerated"
>|> types. I don't really care which of the two it is.
>
>Well, the non-deletable one is just "readonly keys", and that's not nearly
>as flexible as a hash with a specific set of allowed keys.

And consequently easier to implement.

>But I can also see
>the value in having a vanilla "readonly-keys" hash (which would allow you to
>then have a fully readonly hash if you walked the hash and RO'd the values)
>
>I'm sure eveyone can visualize the value of a readonly hash. Let me give
>you my motivation for a deltable-enumerated hash:
>
>   Imagine, for example, any hash you use to implement an object,
>   particularly one widely used in a huge system.

No need to imagine it as I have done such several times.
(100K lines of code, runs with millions of objects in existance,...)
The size of that application is why I am wary of adding extra fields
or extra code paths to critical points.

>   By adding a few lines in
>   the constructor to create the set of allowed keys, you then get
>   protection that the rest of the system is being sociable with your hash,
>   attempting to access those keys and only those keys.

Nothing to argue with there.

>
>   But in order for this to work correctly, all semantics related to allowed
>   keys must be the same as for normal hashes.

Except the different bits. An object based on a "normal" hash can have
stuff dumped in any old key as code sees fit - you have already changed that
bit.

>
>   I guess it's like tie() -- if you do things right, random code out there
>   that uses your tied variable doesn't need to care if it's a tied
>   variable or not.

But tie is in the business of replicating the existing semantics.
We are in the business of changing the semantics.

>
>   Similarly, I think that someone using your enumerated-hash -- if they're
>   using only approved keys -- shouldn't need to care if it's an
>   enumerated-hash or not. To the rest of the system using the hash properly,
>   it *is* just a normal hash.

But if I/we _define_ the semantics of enumerated-hash to mean no-deletes
then that piece of code is not "using the hash properly" by trying
a delete, anymore than it is if it does

sub foo
{
 my $self = shift;
 $self->{__PACKAGE__.'-MAGICAL'} = 42;
 ...

}

Indeed I could make a case for a "base hash" which had a set of fixed
keys which could not be deleted (belong to base class), but allowed
other keys to come and go at the whim of the code as implementation details.
We can get in to a whole protected/private/public sematic debate easily
here. (With suitably snazzy 'new' one can of course mess with allowed
key-set to cope with inheritance.)

The main reason I am persisting with the non-deletable case is because
as Simon et. al. have pointed out what "pseudo-hash" was "for" was
doing struct-oid objects. They failed because they were too slow, too big
and too much like hashes and not enough like structs.

A struct like thing (a truely fixed set of keys) is potentially optimizable
(in perl6 at least).



>
>   Like 'use strict', it doesn't change the semantics of things, but just
>   disallows some things.

e.g. delete ;-)

>
>This natural, drop-in approach feels like The Perl Way to me, which is why
>I feel that keys() should maintain the same returns-only-existing-keys
>semantics.

If we disallow delete then existing keys _ARE_ the allowed keys.

>
>|> The deletable variant is possibly of wider use (e.g. Michael Schwern's
>|> db cache example) but I am as yet unconvinced that case is common enough
>|> (compared to the 'struct' case) to be worth the extra bit and hassle of
>|> defining semantics of C<keys> etc.
>
>It's no hassel to define the semantics of keys() -- heck, we've already done
>it twice :-)

Okay make that "The hassle of getting agrement on the semantics of keys()".

>
>We just need to pick one.

You did not comment on the

   scalar keys()
vs
   scalar values()

idea.

>
>|> >   keys(), values(), and each() return data only for keys that actually
>|> >   exist(). They ignore, for example, keys that are "approved" but don't
>|> >   yet exist. In a scalar context, it returns the number of keys that
>|> >   actually exist.  (It's left to an XS module to provide a way to get
>|> >   the full list of approved keys.)
>|>
>|> You know I differ on this one ;-)
>
>Perhaps my motivation -- for the ability to define the enumeratedness of a
>hash in one place and have eveything else that uses the hash properly see
>normal hash semantics -- sways you a bit?

Not if 'properly' means (by definition) not deleting things.
It is an expectation thing - if I am expecting a 'struct' type object
with a fixed set of keys then delete is a weird thing to do and I would
like it caught.



>
>     Jeffrey
--
Nick Ing-Simmons
http://www.ni-s.u-net.com/



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