could you use array or string as hash key in Perl?

S

Summercool

could you use array or string as hash key in Perl?

and then what if you modify the array or string internally?

i tried

@a = (3,4);

$h{@a} = "ha";

and it took @a as the number 2.
 
P

Paul Lalli

could you use array or string as hash key in Perl?

Array, no. String, yes.

Keys are scalars. If you try to use a non-scalar as a key, that non-
scalar is evaluated in scalar context.
and then what if you modify the array or string internally?

i tried

@a = (3,4);

$h{@a} = "ha";

and it took @a as the number 2.

Right. Because an array in scalar context returns its size. The size
of @a is 2.

I suppose you could use the stringified version of a reference to the
array as the key:
$h{\@a} = "ha";
but I have no idea why you would want to do such a thing.

What are you *trying* to do? What is your end goal?

If you're trying to make a multidimensional structure, you should read
up on references:
perldoc perlreftut
perldoc perllol
perldoc perldsc

Paul Lalli
 
B

Ben Bullock

could you use array or string as hash key in Perl?

and then what if you modify the array or string internally?

i tried

@a = (3,4);

$h{@a} = "ha";

and it took @a as the number 2.

That is the answer to your question, in fact. Perl doesn't like your array
in its hash argument, so it decides to change your array into a scalar. The
number 2 is the "scalar value" of your array, which is the number of
elements in the array.

Thus Perl has already told you that you can't use an array as a hash key.

Of course you can use a string as a hash reference. To find out what Perl
does if you change the value of the string, write a simple test, run it
and see what happens.

#!/usr/bin/perl
use warnings; use strict;
my $string = "frog";
my %animals;
$animals{$string} = "amphibian";
$string = "dolphin";
print $animals{$string}, "\n";
print $animals{frog}, "\n";
 
M

Michele Dondi

could you use array or string as hash key in Perl?

A hash key in current Perl can *only* be a string.

If you want to use an array you have to specify your own array to
string conversion facility in a way that is suitable for the problem
at hand. A simple "@array" may be appropriate or totally wrong,
depending on the actual situation.
and then what if you modify the array or string internally?

"Internally" as opposed to... what?
i tried

@a = (3,4);

$h{@a} = "ha";

and it took @a as the number 2.

Of course, because the array is evaluated in a scalar context and in a
scalar context an array is its size.

You may want to use the reference to the array, in which case the key
will stay the same also if you modify the array later. You just have
to know that the key will *not* be the reference, but also in this
case, its stringification: i.e. do not hope to recover the array
directly from the key, although that is not what you were asking for.
Incidentally, if you want to, then there's a suitable module to do
exactly that.


cognac:~ [16:06:18]$ perl -MData::Dumper -e '@a=3..4; print Dumper \
{ "@a" =>1, \@a => 2 }'
$VAR1 = \{
'ARRAY(0x814fe34)' => 2,
'3 4' => 1
};
cognac:~ [16:06:25]$ perl -le '@a=3..4; $h{"@a"}=3; push @a,1; \
print $h{"@a"} || "undef"'
undef
cognac:~ [16:06:33]$ perl -le '@a=3..4; $h{\@a}=3; push @a,1; \
print $h{\@a} || "undef"'
3


Michele
 
M

Michele Dondi

That is the answer to your question, in fact. Perl doesn't like your array
in its hash argument, so it decides to change your array into a scalar. The
number 2 is the "scalar value" of your array, which is the number of
elements in the array.

Thus Perl has already told you that you can't use an array as a hash key.

This is misleading: using a bare array as hash key is perfectly valid
syntax with an acceptable semantics. So you *can* "use an array as a
hash key": it simply won't do what the OP wanted, whatever it was.


Michele
 
B

Ben Bullock

This is misleading: using a bare array as hash key is perfectly valid
syntax with an acceptable semantics. So you *can* "use an array as a
hash key": it simply won't do what the OP wanted, whatever it was.

In the original poster's post he says
i tried
@a = (3,4);
$h{@a} = "ha";
and it took @a as the number 2.

so he clearly already knows that using an array as a hash key isn't a
syntax error.
 
P

patrick

could you use array or string as hash key in Perl?

and then what if you modify the array or string internally?

i tried

@a = (3,4);

$h{@a} = "ha";

and it took @a as the number 2.

If you want to try and keep the array values you can always use

$h{ join('.', @a) } = 'ha';

print " $h{ join('.', @a) }\n";

====>Patrick
 
B

Ben Morrow

Quoth Paul Lalli said:
Array, no. String, yes.

Keys are scalars.

No, keys are strings (except in tied hashes). This is important, as it
is why using a ref as a key doesn't work.
If you try to use a non-scalar as a key, that non- scalar is evaluated
in scalar context.

....and then stringified.

Ben
 
S

Summercool

yes, i tried using

$h{(3,4)} = "hee";

and print out all the key value pairs.
the key "3 4" show up with a strange character between them.
 
B

Ben Morrow

Quoth Summercool said:
yes, i tried using

$h{(3,4)} = "hee";

and print out all the key value pairs.
the key "3 4" show up with a strange character between them.

That character is the value of $; (by default "\034"), and is how Perl 4
used to do multi-level hashes before Perl 5 and refs were invented.
Using a (literal) list as a key is well worth avoiding nowadays.

Ben
 
M

Michele Dondi

yes, i tried using

$h{(3,4)} = "hee";

and print out all the key value pairs.
the key "3 4" show up with a strange character between them.

That's $;


Michele
 
M

Michele Dondi

If you want to try and keep the array values you can always use

$h{ join('.', @a) } = 'ha';

print " $h{ join('.', @a) }\n";

How does that work with

@a=('a', 'b.c');

and

@a=qw/a b c/;

respectively?

Not to say that your answer is *incorrect* but that one should add
that some care is required.


Michele
 
M

Michele Dondi

Why not? Refs can be stringified, no?

Yes, it can, but he meant exactly what I wrote in another post in this
thread, i.e. that the stringification is a one-way tranformation, so
that when accessing the keys of such a hash one can not hope of using
those as references, which may or may not be what the OP wants, but
that in case happens to confuse some people. See

perldoc -q 'reference.*key'


Michele
 
U

Uri Guttman

A> Why not? Refs can be stringified, no?

and i use refs for keys in a few places. i have both the keys and values
are the same refs (of course i know the keys are stringified). it is a
very good method to use to track a collection of objects or things in
one place say in a class that needs to also know about all of the
objects it has created. you either need to use weak refs or a
delete call on that hash to make sure you don't leak ram.

uri
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top