4

How do Perl hashes work? Are they like arrays in PHP or some completely different beast?

From what I understand all it is is an associative array right? This is what I thought until I began to talk to a Perl programmer who told me I was completely wrong, but couldn't explain it in a way that didn't make my eyes cross.

Anyway, the way that I thought it worked was like this

PHP's:

$argv['dog_name'] = 'missy';
$argv[0] = 'tree';

same as Perl's:

my %argv{'dog_name'} = 'missy';
my $argv[0] = 'tree';

Right? But you cannot print(%argv{'dog_name'}), you have to (revert?) to print($argv{'dog_name'}) which is confusing?

Is it trying to print as a variable now, like you would in PHP, echo $argv['dog_name']; ? Does this mean (again) that a hash is just a PHP associative array with a % to declare but a $ to access?

I don't know, I'm hoping some PHP/Perl Guru can explain how hashes work, and how similar they are to PHP's arrays.

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
ehime
  • 8,025
  • 14
  • 51
  • 110
  • 3
    I edited out the whining and insults and improved the grammar. Also, what you asked for is quite basic - not sure where you found a Perl programmer who wasn't aware of how this works - though, to be honest, I don't expect a random junior Perl programmer to know what "associative array" means without googling it. Or a Java programmer, for that matter – DVK Dec 03 '11 at 08:29
  • Thanks for editing out the garbage, I'm an advanced PHP programmer taking over a PERL project, without really knowing PERL. Which is why the silly question, I'm just trying to get my bearings on PERL lingo I guess and what it really means. – ehime Dec 05 '11 at 16:48

8 Answers8

11

To write

$argv['dog_name'] = 'missy';
$argv[0] = 'tree';

in Perl, you would write it as follows:

$argv{dog_name} = 'missy';
$argv{0}        = 'tree';

if you had strict on, which you should, then you will need to predeclare the variable:

my %argv;
$argv{dog_name} = 'missy';
$argv{0}        = 'tree';

If the above is a bit repetitive for you, you could write it:

my %argv = (
    dog_name => 'missy',
    0        => 'tree',
);

You can find more detail on the perldata manpage.

In short, the reasons why the sigils change from % to $ is that %hash refers to a plural hash (a list of key value pairs), and $hash{foo} refers to a single element of a hash. This is the same with arrays, where @ refers to the full array, and $ refers to a single element. (for both arrays and hashes a leading @ sigil with a subscript means a slice of the data, where multiple keys are passed and a list of values are returned)

Eric Strom
  • 39,821
  • 2
  • 80
  • 152
5

To elaborate slightly on Ambrose's answer, the reason for your confusion is the difference between the philosophy of using sigils in Perl and PHP.

In PHP, the sigil is attached to the identifyer. E.g. a hash identifyer will ALWAYS have a hash sigil around it.

In Perl, a sigil is attached to the way you are accessing the data structure (are you accessing 1 value, a list of values, or a whole hash of values) - for details see other excellent answers such as Eric's.

DVK
  • 126,886
  • 32
  • 213
  • 327
  • So does this mean that if I am trying to access a single variable I would use a cash, but if I'm trying to reference the entire (array?) hash I would be using the percentile? – ehime Dec 05 '11 at 16:50
  • @ehime - Correct. When addressing a hash as a data structure, it's "`%hash`"; when addressing a single element of a hash it's "`$hash{$key}`": `my %hash = ( 1 => 2 ); my $value = $hash{1}; my %hash_copy = %hash;`. However be careful to remember that a reference is a SINGLE element, e.g. a reference to a hash is sigil-ed with `$` always (e.g. `my $hashRef = { 1 => 2}; my $value = $hashRef->{1}; my $copy_of_hash_ref = $hashRef;`. – DVK Dec 05 '11 at 20:52
3

%argv{'dog_name'} is a syntax error. You need $argv{'dog_name'} instead.

But you are correct that a perl hash is just an associative array (why perl chose to use a different terminology, I don't know).

For a complete understanding of hashes, I recommend reading any of the vast number of perl tutorials or books that cover the topic. Programming Perl is an excellent choice, or here's a random online tutorial I found as well.

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
  • 4
    A [hash table](http://en.wikipedia.org/wiki/Hash_table) is the specific type of [associative array](http://en.wikipedia.org/wiki/Associative_array) used by Perl, and "hash" is much easier to say than "associative array". I don't know if PHP uses hash tables or not. – ikegami Dec 03 '11 at 00:36
  • @ikegami This is why I prefer the term "Map" instead of "associative array" to talk about the ADT: the latter, unfortunately though the name, seems to imply some sort of "array-like" semantics (such as those seen with Associative Lists) which is not necessarily true ;-) –  Dec 03 '11 at 00:48
2

I would, as Flimzy, also recommend Programming Perl. As a recent PHP to Perl convert myself, it has taught me a great deal about the language.

The % symbol is used to create a full 'associative array', as we would think of it. For example, I could create an associative array by doing the following:

%hash = ('key1' => 'value1', 'key2' => 'value2');

I could then print it out like so:

print %hash;

The output would be something like:

'key2value2key1value1'

This is, I believe, known as 'list context', since the % indicates that we are talking about a range of values.

On the other hand, if I wanted to access a single value, we would have to use the $ sigil. This, as 'Programming Perl' tells us, can be thought of as an 'S' for 'Scalar'. We have to use the $ sign whenever we are talking about a singular value.

So, to access an individual item in the array, I would have to use the following syntax:

print $hash{'key1'}; 

The same is true of arrays. A full array can be created like so:

@array = ('abc', '123');

and then printed like so:

print @array;

But, to access a single element of the array I would type instead:

print $array[0];

There are lots of basic principles here. You should read about 'list context' and 'scalar context' in some detail. Before long you will also want to look at references, which are the things you use to create multimensional structures in Perl. I really would recommend 'Programming Perl'! It was a difficult read in chapters, but it certainly does cover everything you need to know (and more).

pb149
  • 2,298
  • 1
  • 22
  • 30
2

The sigil changing really isn't as complicated as you make it sound. You already do this in English without thinking about it.

If you have a set of cars, then you would talk about "these cars" (or "those cars"). That's like an array.

my @cars = ('Vauxhall', 'Ford', 'Rolls Royce');

If you're talking about just one car from that set, you switch to using "this car". That's like a single element from an array.

say $car[1]; # prints 'Ford';

Similar rules also apply to hashes.

Dave Cross
  • 68,119
  • 3
  • 51
  • 97
1

The "sigil", i.e. the character before the variable name, denotes the amount of data being accessed, as follows:

  • If you say $hash{key}, you are using scalar context, i.e. one value.

  • For plural or list context, the sigil changes to @, therefore @hash{('key1', 'key2')} returns a list of two values associated with the two keys respectivelly (might be written as @hash{qw(key1 key2)}, too).

  • %hash is used to acces the hash as a whole.

The same applies to arrays: $arr[0] = 1, but @arr[1 .. 10] = (10) x 10.

DVK
  • 126,886
  • 32
  • 213
  • 327
choroba
  • 231,213
  • 25
  • 204
  • 289
  • 3
    The word "context" already means something in Perl, and it does not mean what you describe above! Variables do not determine context, operators/functions determine list or scalar context. The sigils determine "what you are accessing", NOT scalar/list context. "print $hash{key}" imposes LIST context on $hash{key}. The "$" on $hash{key} indicates that you are accessing a single value from the hash. – tadmc Dec 03 '11 at 04:59
1

I would say your confusion is partly caused by one simple fact. Perl has different sigils for different things. PHP has one sigil for everything.

So whether you're putting something into an array/hash, or getting something out, or declaring a simple scalar variable, in PHP you always use the dollar sign.

With perl you need to be more specific, that's all.

AmbroseChapel
  • 11,957
  • 7
  • 46
  • 68
0

I hope that you are not expecting to get a full tutorial regarding perl hashes here. You don't need a Perl guru to explain you hashes, just a simple google search.

http://www.perl.com/pub/2006/11/02/all-about-hashes.html

PS: please increase your accept ratio - 62% is pretty low

Tudor Constantin
  • 26,330
  • 7
  • 49
  • 72