In search of elegant code: Adding to a hash using (key => value) syntax

U

usenet

I prefer this syntax when creating and populating hashes:

my %hash = (
'foo' => 'something',
'bar' => 'else'
);

But suppose that, a little later, I want to add a few more keys/values.
If it were a scalar I could add on using ".=" or if an array I could
"push" onto it - but it seems that for a hash (if I want to keep my
syntax consistent, which I do) I am forced to do something awkward
like:

%hash = (%hash, (
'bax' => 'more',
'baz' => 'stuff'
));

It works, but... is there a more elegant way?
 
A

A. Sinan Unur

I prefer this syntax when creating and populating hashes:

my %hash = (
'foo' => 'something',
'bar' => 'else'
);

But suppose that, a little later, I want to add a few more keys/values.
If it were a scalar I could add on using ".=" or if an array I could
"push" onto it - but it seems that for a hash (if I want to keep my
syntax consistent, which I do) I am forced to do something awkward
like:

%hash = (%hash, (
'bax' => 'more',
'baz' => 'stuff'
));

It works, but... is there a more elegant way?

That makes a temporary hash consisting of %hash, and the two new
key-value pairs you want to add, and then assigns that to %hash. What is
the point of engaging in such gross inefficiency?

$hash{bax} = 'more';
$hash{baz} = 'stuff;

is elegant enough for me and easier to maintain. But, if you insist, why
not use a hash slice?

@hash{qw(bax baz)} = qw(more stuff);

#!/usr/bin/perl

use strict;
use warnings;

my %hash = (
foo => 'something',
bar => 'else',
);

@hash{qw(bax baz)} = qw(more stuff);

print "$_ => $hash{$_}\n" for keys %hash;

__END__

Sinan
 
J

Jürgen Exner

I prefer this syntax when creating and populating hashes:

my %hash = (
'foo' => 'something',
'bar' => 'else'
);

But suppose that, a little later, I want to add a few more
keys/values. If it were a scalar I could add on using ".=" or if an
array I could "push" onto it - but it seems that for a hash (if I
want to keep my syntax consistent, which I do) I am forced to do
something awkward like:

%hash = (%hash, (
'bax' => 'more',
'baz' => 'stuff'
));

It works, but... is there a more elegant way?

What's wrong with a simple
$hash{'bax'} = 'more';
$hash{'baz'} = 'stuff';

jue
 
S

Steven Kuo

I prefer this syntax when creating and populating hashes:

my %hash = (
'foo' => 'something',
'bar' => 'else'
);

But suppose that, a little later, I want to add a few more keys/values.
If it were a scalar I could add on using ".=" or if an array I could
"push" onto it - but it seems that for a hash (if I want to keep my
syntax consistent, which I do) I am forced to do something awkward
like:

%hash = (%hash, (
'bax' => 'more',
'baz' => 'stuff'
));

It works, but... is there a more elegant way?





If you insist on that adhering to that style, you could try a tied
hash. You'll have to judge whether it's "elegant" -- to me it can
also be a bit "dangerous" if one doesn't understand the implications
of overwriting methods:

#!/usr/bin/perl

package CumulativeHash;
require Tie::Hash;
@ISA = ('Tie::StdHash');

sub CLEAR
{
# does not clear previous entries
}

1;

package main;

use strict;
use warnings;
use Data::Dumper;

my %hash;

tie %hash, 'CumulativeHash';

%hash = (
foo => 'something',
bar => 'else',
);

%hash = (
'bax' => 'more',
'baz' => 'stuff',
);

print Dumper \%hash;
 
U

usenet

What is the point of engaging in such gross inefficiency?
For the only reason that the syntax is more consistent with the
statement that created the hash. But I never said it was elegant (or
efficient).
It gets a bit repetitious to keep saying "$hash=..." if I want to add a
dozen or more pairs. And it's not the same style of syntax that
created the hash. But, yeah, it works, of course.
Yuck. Maintaining that across more than a few pairs would be awful.
I'd rather be repetitious.

It just seems like other data types have operators designed to append
to them ('.=', push/unshift, '>>'). No such "append" operator exists
for hashes. That's a bummer, IMHO.
 
U

usenet

oooooo, that's interesting (and a bit over my head - I need to study up
a bit on what's going on here). Of course, it does seem like a big
hammer for a small nail. It would be nice (IMHO) if Perl had an
"append" operator for hashes, like it does for other types of data.
 
T

Tad McClellan

It just seems like other data types have operators designed to append
to them ('.=', push/unshift, '>>'). No such "append" operator exists
for hashes.


Yes it does.

The assignment operator (=) makes a hash get bigger, just as a
push() makes an array get bigger.
 
J

John Bokma

Tassilo v. Parseval said:
push %hash, key1 => 1,
key2 => 2;

Funny, you should have seen the post I just deleted :)

I was including something like: it's silly to use push, since push assumes
some order (I mean, what is unshift going to do, and pop, and shift). Also,
one can overwrite keys.
Slicing is one way to do it, but then slicing works on arrays as well.
Hashes just lack a dedicated push operator which is partly due to their
slightly different nature (for instance there is no conceivable concept
for pushing a single value onto a hash since it has no tail after which
to append a datum).

Ok, too fast again :-D
 
T

Tassilo v. Parseval

Also sprach John Bokma:
Funny, you should have seen the post I just deleted :)

I haven't. :)
I was including something like: it's silly to use push, since push assumes
some order (I mean, what is unshift going to do, and pop, and shift). Also,
one can overwrite keys.

Yes, at some point the analogy stops working. OTOH, 'pop' and 'shift'
could be made synonyms to 'delete'. Whereas 'unshift' would necessarily
be the same as 'push'.

Tassilo
 
T

Tassilo v. Parseval

Also sprach Tad McClellan:
Yes it does.

The assignment operator (=) makes a hash get bigger, just as a
push() makes an array get bigger.

Only on per-key basis, not on the hash as a whole. It's not the same
thing as push() at all. There is no reason why push couldn't be extended
to work on hashes, too:

push %hash, key1 => 1,
key2 => 2;

Slicing is one way to do it, but then slicing works on arrays as well.
Hashes just lack a dedicated push operator which is partly due to their
slightly different nature (for instance there is no conceivable concept
for pushing a single value onto a hash since it has no tail after which
to append a datum).

Tassilo
 
I

Ilmari Karonen

Tassilo v. Parseval said:
Also sprach John Bokma:

Yes, at some point the analogy stops working. OTOH, 'pop' and 'shift'
could be made synonyms to 'delete'. Whereas 'unshift' would necessarily
be the same as 'push'.

No, shift and pop should be equivalent to:

sub pop_hash (\%) {
my ($hash) = @_;
keys %$hash; # reset iterator!
my @pair = each %$hash or return;
delete $hash->{$pair[0]};
return @pair;
}

Ideally the implementation wouldn't need to use the internal hash
iterator at all. Proper behavior in scalar context I'll leave for
others to decide.
 
B

Brian McCauley

I prefer this syntax when creating and populating hashes:

my %hash = (
'foo' => 'something',
'bar' => 'else'
);

But suppose that, a little later, I want to add a few more keys/values.
If it were a scalar I could add on using ".=" or if an array I could
"push" onto it - but it seems that for a hash (if I want to keep my
syntax consistent, which I do) I am forced to do something awkward
like:

%hash = (%hash, (
'bax' => 'more',
'baz' => 'stuff'
));

It works, but... is there a more elegant way?

Well just in terms of formatting I'd say it's more elegant and consistant as

%hash = (
%hash,
'bax' => 'more',
'baz' => 'stuff',
);
 
A

axel

Subject: Perl & academia, maybe OT [was Re: In search of elegant code: Adding to a hash using (key => value) syntax]
Newsgroups: comp.lang.perl.misc
References: <[email protected]> <[email protected]>

[something not related to my follow-up]

Brian, I notice that you are posting from Birmingham University...
interestingly I popped into the bookshop there a couple of days
ago and see that the stock has not improved since my days at the
university. Out of curiosity I looked to see if there were any Perl
books - not a single one. Now, I do put this down to the bookshop
having a poor selection of books - let's face it students have
little enough money as it is to spend on beer let alone books. But
I was just wondering out of idle curiosity if any courses in Perl
are taught?

Axel
 

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

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top