Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Perl have an associative array type that can have any type of keys?

It seems that Perl can only have strings as the keys of a hash. (Has this been changed in a certain version of Perl?) It is very limiting to only be able to use strings as the key. What if I wanted an object or an array to be the key? In Python it is easy to use an array, tuple, and other objects that can compare, as dict keys. Perl does have the ability to compare things like arrays for equality, so I don't see why they can't be used as mapping-type keys.

Isn't there a way to use any key type in Perl? Is there a module that provides this?

like image 840
user553702 Avatar asked Aug 16 '11 06:08

user553702


People also ask

What is associative array in Perl?

Associative arrays are a very useful and commonly used feature of Perl. Associative arrays basically store tables of information where the lookup is the right hand key (usually a string) to an associated scalar value. Again scalar values can be mixed ``types''.

Which key is used in associative array?

Traversing the Associative Array Example: In Associative arrays in PHP, the array keys() function is used to find indices with names provided to them, and the count() function is used to count the number of indices.

Why are associative arrays called hashes in Perl?

Associative arrays, also frequently called hashes, are the third major data type in Perl after scalars and arrays. Hashes are named as such because they work very similarly to a common data structure that programmers use in other languages--hash tables.

What is meant by associative array?

In computer science, an associative array, map, symbol table, or dictionary is an abstract data type that stores a collection of (key, value) pairs, such that each possible key appears at most once in the collection. In mathematical terms an associative array is a function with finite domain.


2 Answers

Contrary to what you said, Perl does NOT have the ability to compare things like arrays for equality as you claim. For starters, Perl has no definition for array equality. And if the definition requires comparing the contents of the array, then Perl doesn't have definitions of equality for most things that can be found in an array either.

The closest Perl has for a definition of equality arrays is their address. If that's what you want to use, then it's quite easy:

$key = ['a', 'b'];
$hash{$key} = [ $key, $val ];   # Prevents the key from being freed.
print $hash{$key}[1];

Otherwise, Perl leaves it up to you to implement what you want instead of forcing you to use what it provides. I see two main approaches.

A tied hash, basically code that presents the interface of a hash without actually being a hash table, can support any key type. You could use it to define your version of array equality. There might even be an existing module (although I didn't see one after a very quick search).

Another approach would be to create a function that produces a unique key from the key expression.

sub key{ "@_" }  # Overly simplistic?
$hash{key('a', 'b')} = $val;
print $hash{key('a', 'b')};
like image 188
ikegami Avatar answered Oct 07 '22 01:10

ikegami


AFAIK Perl simply stringifies the keys?

package Foo;

use Moose;
use overload ('""' => \&stringify);

sub stringify {
    return "xxx";
}

package main;

use v5.10;
use Data::Dump 'pp';

my $foo = Foo->new;
my $hash = {$foo => 'bar'};
say pp($hash); // { xxx => "bar" }

This way you can also use whatever you want as a hash key. See also this thread on Perl Monks.

As for the equality, take a look at equality operators in perlop. The == operator compares numerically, the eq operator compares stringwise. This means that for example (4, 2) == (1, 2) is true (as scalar (4, 2) is 2), which might be a surprise for you.

like image 43
zoul Avatar answered Oct 07 '22 00:10

zoul