On Tue, Jul 31, 2001 at 09:26:03AM -0500, Miller, Scott L wrote: > > Just want to reiterate the point that if we can change the value of a > > key, we should be able to delete the key *and* reinstate it. > > > > my %hash = (a => 1, b => 2); > > readonly %hash; > > $hash{a} = "foo"; > > delete $hash{a}; > > $hash{a} = "bar"; > > Probably a newbie type question, but: > > Why would you want to do this, when you can simply say: > > $hash{a}="foo"; > $hash{a}="bar"; > > and get the same affect? It seems to me that it would be much more > expensive to delete the key between the assignments... Sorry, the example was just a simple illustration of the expected behavior. I was just pointing out that you can reinstate a deleted key on a readonly hash (assuming it's part of the allowed set). There are times when the difference between "exists $hash{a}" and "defined $hash{a}" become important (otherwise, exists() wouldn't exist). If it doesn't exist, it means you never put anything in that key. If it's not defined, it means you put something in that key and the value happens to be not defined. My primary example, and the one I slammed into with pre-5.6 pseudo-hashes, is this: Let's say you have an object (modeled as a hash ref) which represents the columns of a table in a database (a la Class::DBI). You only grab the values from the database when they are requested. A very simple way to handle this is: sub get { my($self, $col) = @_; $self->{$col} = $self->_fetch($col) unless exists $self->{$col}; return $self->{$col}; } Values in the database may be null (undef), so I must use exists(). Presumably I've set up $self so that it's a readonly hash with keys for all the columns in the table, but I've deleted all those keys when I initialize the object. sub new { my($class) = shift; # Presumably this sort of thing would be encapsulated. my $self = { map { $_ => 0 } $class->columns }; readonly $self; delete $self->{$_} foreach keys %self; return bless $self, $class; } So a nice, new, fresh object will be a readonly hash who's keyset is the names of all the columns in the table. Then when I say: print $self->get("foo"); for the first time, $self->{foo} does not exist, it goes and checks the database. Second time, $self->{foo} exists, and it just returns its value. Pseudo-hashes currently allow this sort of behavior and It Is Good. Without it, I would have to maintain a seperate hash of what columns I've accessed and which I haven't. Not a huge problem, but rather annoying and double the memory. Essentially, delete/exists is just bookkeeping. It shouldn't be effected by or effect the clamped nature of the hash. Clamping/readonly is for protecting the keyset, not the values (at least in this context). If you can say this: %foo = (a => 1, b => 2); $foo{a} = "this"; readonly %foo; $foo{a} = undef; ie. you can alter the value of 'a' after its been clamped. Then you may as well be able to delete 'a' entirely. This also has the nice effect of making keys() and values() work properly. My experience with pseudo-hashes says this is the Right Thing To Do. -- Michael G. Schwern <schwern@pobox.com> http://www.pobox.com/~schwern/ Perl6 Quality Assurance <perl-qa@perl.org> Kwalitee Is Job OneThread Previous | Thread Next