Another trap: length of a list constant

ferreira on 2007-08-07T13:41:05

List constants are weird. The documentation warns you about this. They are lists and not arrays and call for convoluted expressions like the ones below for doing some common tasks.

(WEEKDAYS)[1..5] # to slice

@week_names_in_lojban{(WEEKDAYS)} # to index slices
#BEWARE! @week_names_in_lojban{+WEEKDAYS} gives you a suspicious warning
And so I wanted to take the length of a constant list, and naively tried:
use constant LIST => qw(A B C);
(LIST)+0
which worked right. But
use constant LIST => qw(A);
(LIST)+0
give me zero (because that's the result of "'A'+0") and
use constant LIST => ();
(LIST)+0
ends in zero as well (because it is "undef+0"). Well, you'll see that in a flash IF you have warnings on. (And yes, I stumbled with the strong suggestion to not use constants with more than one value in scalar context, because they return the number of values today, but that may change.) But the end of story is that it seems like you don't have a good expression to compute the length of a generic list constant. A seemingly sensible alternative is using a constant array ref.
use constant LIST_REF => [qw(A)];
@{+LIST_REF}+0 # ugh! but works

I have to admit that using Readonly is much prettier. It is really a win to preserve the type and the visual distinction among scalar/array/hash with the sigil. But hey, I wanted to use that in tests — requiring Readonly for writing beautiful test code feels like overkill, but maybe that was what I should do.

use Readonly;
Readonly::Array @LIST = qw(A B C);
#Readonly::Array @LIST = qw(A);
#Readonly::Array @LIST = qw();
scalar @LIST # works alright in all three cases
That reminded me of Ingy's manifesto in Module::Install::Philosophy. Mainly, the phrase that goes similar to this: I have a dream that one day my modules will not be judged by the number of their prerequisites. But... I was going to rant about failing tests of a not-so-urgent prerequisite (but Readonly distribution is flawless according to CPAN testers). And what about performance? What about the OS-challenged and ISP-challenged people that can't install hybrid modules that need C compilation? What about [many other things]? Well, excuse me. Too much digression :/