I was writing a CGI script that displayed a table of IP addresses under DHCP control. I wanted to display addresses that had been allocated, expired and/or in conflict. This was written as a table, with the background cell colour indicating the status. I then had to add a legend, to explain what the colours meant, and at the same time, I thought it would be nice to display the number of values encountered for each legend key.
The hash keys were nothing more than the HTML background colour to be used. Here's the problem, without running the code, what do you think the following will print out:
#! /usr/bin/perl -w use strict; use constant FOO => 'foo bgcolor'; use constant BAR => 'bar bgcolor'; sub keyname { return shift() % 2 ? FOO : BAR } # to simplify my( %g, %h ); $g{ keyname(20) } = 6; $g{ keyname(21) } = 12; $h{ FOO } = 18; $h{ BAR } = 24; print "g: $_ is $g{$_}\n" for keys %g; print "h: $_ is $h{$_}\n" for keys %h;
In the %h hash, I am assigning based on a defined constant. In the %g I am not sure which key to use. All I have is a value, so I call a subroutine that determines the appropriate key. As it turns out, and in hindsight it is perfectly obvious, the two sets of keys assignments are not equivalent. Here is the output:
g: foo bgcolor is 12 g: bar bgcolor is 6 h: BAR is 24 h: FOO is 18
When I was trying to debug the code, however, I couldn't understand why $g{FOO} was returning undef. I was having an impedance mismatch between how I thought constants should behave and how they do behave.
It turns out there are two ways to fix this. The problem is that $h{FOO} is using FOO as a string... literally 'FOO'. It is not calling the constant FOO subroutine. Bleagh! I could have either written the keyname thusly sub keyname { return shift() % 2 ? 'FOO' : 'BAR' } or else I could have written $g{+FOO} when refencing the hash. I tend to discount to first solution, as it appears to circumvent the whole point of using constants. I also thing that the +FOO is a bit of a wart that reveals the retrofittedness of constants in Perl, but I guess I can live with that, at least until Perl 6. So that's what my code now looks like.
<update> yes, as tye points out, there are many ways of writing +FOO. That's the point. You're exposing the gory details of how constants are hacked up in Perl, and I find the whole concept a bit ugly. Especially the way constants fall apart across subroutine boundaries.</update>
Mind you, some people hate using constants, but that's another story.
--
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
(tye)Re: use constant hash keys
by tye (Sage) on Jul 31, 2001 at 00:34 UTC |