August 2010 Archives

Yet another readonly module

I’m done with Readonly. It has served it’s purpose but I’m frustrated to the point of writing a replacement. I still think it’s a good idea to declare variables readonly, but as an implementation I find Readonly unworkable. The problem is two-fold.

Maintenance.

Readonly hasn’t been updated in 6 years. It has collected quite a list of bugs. Not all of them can be fixed, but most that can be are either trivial or already have patches. Fact is it hasn’t been done and I have my doubts on whether it will be done.

Broken by design

Readonly has a number of design issues. It uses ties for its implementation. This is not only slow, but also rather buggy. There are lots of subtle corner cases to ties, and Readonly has probably run into a lot of them, though I suspect there may be more waiting to be discovered. Most of its bugs are related to this. There are some more issues but they are relatively minor compared to this. Your variable shouldn’t have unexpected behavior simply because it’s readonly, that’s madness.

The sad part is that ties aren’t really necessary here. Perl 5 has always supported real readonly variables, and though this functionality wasn’t exposed for Perl code until 5.8. It makes a lot more sense to use the real thing. The optional Readonly::XS tries to do that for scalars, but in the most common use case of Readonly (using sub Readonly on a scalar) it isn’t actually used (this is probably a bug).

Introducing Const::Fast

So I’ve written my own module, Const::Fast. It does not use ties or XS. It has one function const, that simply makes a scalar, array or hash recursively readonly. Without the speed penalty of ties and without the bizarre class of bugs that they bring.

Why uvar magic must die

Uvar magic must die. Maybe it’s too late for a complete removal, but it’s use should at least be discouraged. One of the reasons is that it’s actually two very different things that don’t have all that much in common.

Scalar uvar magic

Scalar uvar magic isn’t actually evil, it’s just fairly useless. It’s a way to add get and set hooks to scalars. It may have been a useful interface back when it was introduced in 1993, but with the introduction of custom magic vtables in 5.8 it stopped particularly useful. The new interface is more powerful in many ways and in typical cases it that takes less code to use. There’s absolutely no reason why anyone should still be using scalar uvar magic unless you have to maintain compatibility with 5.6.

Hash uvar magic

I blogged before about what hash uvar magic is and how to use it. Hash uvar magic is an abomination. It is the single most horrible interface in the whole of the perl API and that is an achievement. p5p must have been asleep when they allowed it in.

You may wonder, why is it so evil? It abuses the relatively sane interfaces of scalar uvar magic and uses for some completely different purposes. Parameters and even properties of the parameters get completely new functions. It’s a case of fitting a square peg in a round hole.

square peg in a round hole

The callback doesn’t even receive it’s most important parameter (the key value) as an argument! You have to use mg_find to extract it out of one of the arguments (the hash). Equally bad, there’s absolutely no way to add data to the magic (other than adding more magic) because all possible fields are already in use: uvar itself uses mg_ptr and mg_len. The hash magic clobbers both mg_obj and uf_index.

The saddest thing is that all of this wasn’t necessary. It should have been easy to define some new kind of magic that passes it’s data in a more sane way quite easily. Maybe it’s not too late yet and the current API can be deprecated in favor of something sane (it’s not like people are using it a lot so far).

What are magic hash key transformations

Some weeks ago I posted a brain-dump that only got reaction like that looks interesting, but I have no idea what you’re talking about, so I’m going to try to explain what I was doing.

Since 5.10, perl supports uvar magic on hashes, though I called it magic hash key transformations because that gives at least tries to describe what it does. This was implemented to make fieldhashes possible. It’s an interface that does only one thing: when a hash element is accessed in any way the callback is called. The callback can’t change the semantics of the operation (unless it dies), all it can do is change the value of the key looked up. So it can transform $hash{A} into $hash{B}.

Nothing more, nothing less.

AFAIK, there are only 4 modules on CPAN that use it

  • Hash::Util::FieldHash: The original user of this API.
  • Hash::FieldHash: A simpler reimplementation of H::U::F.
  • Variable::Magic: A module making magic accessable from perl (instead of XS). This means you can actually use this stuff without hacking XS (though it will obviously be a bit slower).
  • Class::Private: a module I wrote and used as example in my previous post. It rewrites $hash{key} to $hash{‘Package::key’} in order to prevent collisions in key values between sub- and super-classes.

Why aren’t more modules using this? Probably because it’s fairly limited in what useful things it can do. I’m sure there are more uses of it, but I can’t think of any (that’s not true, for my previous post I was considering writing Acme::Keys::Rot13). It’s an interface with a limited purpose, though it can be useful sometimes.

In my next post, more about the darker side uvar magic.

Send-a-newbie, the report

Day zero

Day one

A busy day! I had to get up early to be at the venue on time, despite not having slept as muc…

About Leon Timmermans

user-pic