•Re: use constant for strings
by merlyn (Sage) on Apr 18, 2003 at 17:48 UTC
|
Ahh yes, you've hit the bugaboo with using =>. It's very very very quotey. It quotes even subroutine names (as long as they are simply bare words), which is what a use constant ends up being. Either switch to comma instead of arrow, or invoke your subroutine:
my %capitol_map = (
WISCONSIN() => "Madison",
ILLINOIS() => "Springfield",
...
);
-- Randal L. Schwartz, Perl hacker
Be sure to read my standard disclaimer if this is a reply. | [reply] [d/l] [select] |
Re: use constant for strings
by dws (Chancellor) on Apr 18, 2003 at 17:52 UTC
|
I had assumed that in the hash creation, that the constants would be interpolated into their text values.
The tokens WISCONSON and ILLINOIS are being treated as "barewords", thanks to '=>'. To force them to be interpeted, you can do something like
my %capitol_map = (
(WISCONSON) => "Madison",
...
or risk a bit of duplication and write
my %capitol_map = (
WI => "Madison",
...
| [reply] [d/l] [select] |
Re: use constant for strings
by perrin (Chancellor) on Apr 18, 2003 at 17:58 UTC
|
I advise you not to use the "constant" module for this reason. It comes up in other places as well (double-quoted strings, for example) and forces you to think of these contants as subroutine calls rather than constant values. You're better off just using global variables for them instead. | [reply] |
Re: use constant for strings
by ChemBoy (Priest) on Apr 18, 2003 at 17:57 UTC
|
The problem is your use of the stringifying comma (=>). The parser sees it following a bareword, and assumes that you want the string value "WISCONSIN" rather than the return value of the subroutine &WISCONSIN().
There are various ways around this: you can change the fat comma to a regular comma, or you can change the bareword into something Perl recognizes as subroutine call (since that's what a constant is actually implemented as).
my %capitol_map = (
WISCONSIN , "Madison",
ILLINOIS , "Springfield",
...
);
or
my %capitol_map = (
&WISCONSIN => "Madison",
ILLINOIS() => "Springfield",
...
);
Update: it has been suggested that both of these have the potential to confuse future readers of your code, which I find a strong enough argument to recommend against using this particular construct. Use the skinny comma or dws's suggestion above, instead. </update>
I was going to suggest %map = ( +WISCONSIN => "Madison"), but that doesn't actually do the trick with my perl. It does, however, work for getting keys back out of the hash, should you ever need to:
print $capitol_map{+WISCONSIN};
If God had meant us to fly, he would *never* have given us the railroads. --Michael Flanders | [reply] [d/l] [select] |
(jeffa) Re: use constant for strings
by jeffa (Bishop) on Apr 18, 2003 at 17:50 UTC
|
UPDATE: i should have checked before i posted ... just do
what merlyn said. :)
Nope, that's not how constants work.
Actually, a constant is really a Perl sub that
returns the 'constant' value. Try using another hash:
use constant WISCONSIN => "WI";
use constant ILLINOIS => "IL";
my %abbrev_map = (
WI => 'WISCONSIN',
IL => 'ILLINOIS',
);
my %capitol_map = (
WISCONSIN => "Madison",
ILLINOIS => "Springfield",
);
my $abbrev = "WI";
if ( exists $abbrev_map{$abbrev} ) {
print "capitol = $capitol_map{$abbrev_map{$abbrev}}\n";
}
Alternatively ... i have a strong suspicion that a CPAN
module might exist that contains states and their capitols.
UPDATE 2:
Well, can't seem to find one. The closest matches are:
which contain American states and their abbreviations, but
no capitols .... hmmmm .... sounds like a new CPAN module is
in the works.
jeffa
L-LL-L--L-LL-L--L-LL-L--
-R--R-RR-R--R-RR-R--R-RR
B--B--B--B--B--B--B--B--
H---H---H---H---H---H---
(the triplet paradiddle with high-hat)
| [reply] [d/l] |
Re: use constant for strings (unary plus)
by Aristotle (Chancellor) on Apr 18, 2003 at 18:40 UTC
|
Besides the parens (around or following) and the ampersand, you can use an unary plus - the Perl way of disambiguating whether you are referring to an expression or something else.
my %capitol_map = (
+WISCONSIN => "Madison",
+ILLINOIS => "Springfield",
...
);
See rir's post below..
Makeshifts last the longest.
| [reply] [d/l] |
|
|
use constant KEY => "key";
my %h = ( +KEY => "data" , KEY() => "data",);
$, = "\n";
print "Perl vers: $]", keys %h;
Outputs:
Perl vers: 5.006001
KEY
key
| [reply] [d/l] [select] |
|
|
| [reply] |
|
|
personally, i don't like the unary plus. how does it make things less ambiguous? "plus" means "not an expression"? it's not clear. besides, we have sigils to remove ambiguity, anyway. i'd recommend &WISCONSIN, or if you're afraid of side effects (which won't occur with constants,) use &WISCONSIN(). more to write, but leaving less to the imagination.
~Particle *accelerates*
| [reply] [d/l] [select] |
|
|
I don't want to use the sigil simply because it disables the prototype and thus the constant-ish nature as mentions of the "constant" become regular runtime function calls (otherwise they'd be substituted at compile time). I might as well just use a variable.
Seeing as the unary plus doesn't work here, the next best thing I'd prefer would be (WISCONSIN) - with the parens following it looks quite awkward IMHO.
I like the unary plus in other situations and use it lots though - f.ex
map +(foo($_, "bar"))[3], @baz;
where I would otherwise be forced to use curlies
map { foo($_, "bar"))[3] } @baz;
or another extra pair of parens.
map((foo($_, "bar"))[3], @baz);
I don't like either of the latter two, though I realise quite a few people here will disagree. I think the last one at least is certain not to win any prizes for beauty..
Makeshifts last the longest. | [reply] [d/l] [select] |
|
|
|
|
|
|
|
|
|
i'd recommend &WISCONSIN, or if you're afraid of side effects (which won't occur with constants,)
Then I guess you've never noticed how "constants" are implemented by default when one uses h2xs. I've seen &CONST cause warnings in real code because of that.
But I don't use &CONST because I know it passes @_ to the CONST subroutine and I don't want whoever ends up maintaining my code wondering why I'm passing @_ in. Just because it (usually) works, doesn't mean it makes sense. (:
- tye
| [reply] [d/l] [select] |
Re: use constant for strings
by Enlil (Parson) on Apr 18, 2003 at 17:55 UTC
|
The constant you are assigning is WISCONSIN to WI not WI to WISCONSIN. That said there is also a difference between WI and "WI" as use constant WI => "WISCONSIN";
use constant ILLINOIS => "IL";
my %capitol_map = (
WISCONSIN => "Madison",
ILLINOIS => "Springfield",
);
my $abbrev = WI;
if ( exists $capitol_map{$abbrev} ) {
print "capitol = $capitol_map{$abbrev}\n";
}
else { print "False" }
will print the name of the capitol, and use constant WI => "WISCONSIN";
use constant ILLINOIS => "IL";
my %capitol_map = (
WISCONSIN => "Madison",
ILLINOIS => "Springfield",
);
#THE LINE BELOW WAS CHANGED
my $abbrev = "WI";
if ( exists $capitol_map{$abbrev} ) {
print "capitol = $capitol_map{$abbrev}\n";
}
else { print "False" }
will not.update:Hrm.. maybe I missed the fact that the OP might have wanted the WISCONSIN in the hash to become WI not the WI in the my $abbrev to become WISCONSIN ... so my answer would then be incorrect as i seem to be answering the wrong thing. -enlil
| [reply] [d/l] [select] |
Re: use constant for strings
by rir (Vicar) on Apr 18, 2003 at 19:10 UTC
|
Also consider Bolivia when you code stuff like this. :-) | [reply] |
Re: use constant for strings
by dragonchild (Archbishop) on Apr 21, 2003 at 14:10 UTC
|
Personally, I wouldn't use this way of doing things. I would, instead, create an object that encapsulates this information, as thus:
| [reply] [d/l] |