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

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

Thread Previous | Thread Next
Jeffrey Friedl
November 2, 2001 09:33
Re: restricted hashes, and other readonlyness (was "clamp...")
Message ID:

Nick Ing-Simmons <> wrote:
|> >#2 are provided by a hash with a fixed keyset, nothing more,
|> >nothing less.  delete(), exists(), keys() all work like regular
|> >hashes.  This is the basic struct.
|> I happen to want 2a which stops parts of the program deleting random keys
|> in my hash.

I can appreciate the desire for these semantics.

Of course, you can just give the hash readonly keys, as opposed to the
extended semantics being discussed, and your problem is solved.

Making the keys readonly wouldn't be appropriate for many situations, so if
you wish more flexability, one approximation might be for us to define the
semantics that you can't delete() a key whose value has been marked

The devil's advocate will say "well, I want a value that someone can be
changed, but just not delete", and I'd say "I can appreciate the desire for
these semantics -- too bad" :-)

But, to brainstorm a bit on other things that could plausably be done:

    An easy way to implement it is to add a bit to the hash entry 'struct
    he', but since there's no room for it, it would have to be by adding at
    least a byte (which often ends up getting padded to a word) for each
    key, which is probably not appealing.

    Another way would be to hang a private, internal hash off of the hash's
    struct, which lists non-deletable keys. Perhaps one of the current
    members of 'struct xpvhv' is unused for user hashes (xmg_stash?). It's
    not a super clean solution, but would have no impact on hashes that had
    no undeleteable keys.

|> >On Thu, Nov 01, 2001 at 07:33:49AM -0800, Jeffrey Friedl wrote:
|> >> 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.

Yes, that's a readonly hash (or, more specifically, a fixed-key hash).
We're talking about adding a richer set of semantics, as well.

|> >Finally, the argument that we can shave a few bytes of memory by
|> >adding a few inconsistencies into the implementation seems a throwback
|> >to pseudo-hashes.
|> Aside from the (now dead) abuse of keys - the other cause for which I
|> am Devil's advocate is the minimalist one:
|> One (existing) flag bit SvREADONLY
|>  - error on get of non-existing key
|>  - error on set of non-existing key
|>  - delete is not allowed
|>  - keys is just existing code
|>  - therefore exists on deleted key is non issue
|> I want folk to explain clearly the draw back of that

There is no drawback to this. It's wonderful. It's a fixed-key hash,
and is what you get with (SvREADONLY(hv) && ! SvPSEUDOENUMERATED(hv)).

|> and why it is not sufficient for appication X.

I don't think X is implemented in Perl. Windows might be, though.
Windows crashes much more than X, so I'm guessing that they could use
these pseudo-enumerated hashes.

(Sorry, that's just a little joke. Not even worth a smiley.)

Seriously, again, it's the same situation I described yesterday.
I've got these hashes (objects, if you like) that random code out
there uses. As with many hashes that are used to implement objects,
the set of keys this object X uses is restricted to a specific set.
It's my hope that all the random code out there that is using the
object is doing so nicely, but how do I know?

"Nicely" might be defined as "if you have a {FirstName} element, there must
be a {LastName} element". Or, it might be that "{Age}" must be numeric. Or
perhaps "{Color}" represents a shade I like.

Of course, there's nothing we can put into the core (at least not
reasonably) to ensure that random code is behaving nicely with these
semantics of "nicely". But there are some semantics that we can deal with,
such as "use only these keys, and no others" and "don't change these
values", etc.

So, what *can* we do?

 *  However, we can 'use warnings' to catch some kinds of errors like:
       $obj->{SomeTypoHear} += 1;

Additionally, with just a few hooks in the core, we can:

 *  We can make it an error to access a key that's not approved, to catch:
       if ($obj->{SomeTypoHear})

 *  We can make it an error to set a key that's not approved, to catch:
       $obj->{SomeTypoHear} = 1;

 *  We can set values we don't want others to change to SvREADONLY.
    This won't (currently) stop them from being deleted, but in any case
    it's a good first line of defense.

Now, if you know the situation, it may well be sufficient to just make
the whole hash readonly. If you can do it, lucky for you.

But at least in my world, there are many object hashes where the normal
random code needs to deal with adding keys, deleting keys, checking for
existance and definedness of keys, updating values, etc. This is fine, so
long as they stick to the set of approved keys. If they don't, it'd be nice
to hear about it.

Of course, just making sure they stick to the set of approved keys is
not sufficient for anything, just as 'use strict' isn't sufficient to
ensure bug-free code.

Of course, there *are* hooks, already, to provide checks for even very
high-level sementics ({Age} must be numeric, etc.). It can all be done with
tie(). But tie() is a big, ungainly stick not always appropriate.

The changes proposed draw a balance among the oft-conflicting
considerations. It buys you a lot but not everything, for many situations
but not all, but all at very little cost (except the man years going into
this discussion :-)


Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About