Newbee question about "missing" hash methods +, += and <<

Hi,

I’m wondering if there is a special reason for the class Hash not to have the methods +, += and <<
just like Array. I would find it intuitive if I could do something like this

testhash = Hash.new
testhash << {"some key" => "some value"}

or even

secondhash = {"some other key" => "some other value"}
testhash += secondhash
			 #->  {"some key" => "some value", "some other key" => "some other value"}

thats the behaviour of arrays and I know that I could extend the class Hash, so that its supported.
I simply want to know if there is a special reason why it is not supported by default.

benny

thats the behaviour of arrays and I know that I could extend the class
Hash, so that its supported. I simply want to know if there is a special
reason why it is not supported by default.

What do you do if the key exist ?

Array#+ always add elements, with Hash#+ keys will be added only if the
key don't exist otherwise the old value is replaced.

Guy Decoux

“benny” linux@marcrenearns.de schrieb im Newsbeitrag
news:20040127171647.756933c0@bava.ho…

Hi,

I’m wondering if there is a special reason for the class Hash not to
have the methods +, += and <<
just like Array.

First of all, no class has a method “+=”. Instead this is a syntactic
shortcut that transforms “a += b” into “a = a + b” - whatever ‘a’ and ‘b’
are.

I would find it intuitive if I could do something like this

testhash = Hash.new
testhash << {“some key” => “some value”}

There is “update”:

irb(main):004:0> testhash = {}
=> {}
irb(main):005:0> testhash.update( {“some key” => “some value”} )
=> {“some key”=>“some value”}
irb(main):006:0> testhash
=> {“some key”=>“some value”}

secondhash = {“some other key” => “some other value”}
testhash += secondhash
#-> {“some key” => “some value”, “some other key” => “some other
value”}

irb(main):007:0> secondhash = {“some other key” => “some other value”}
=> {“some other key”=>“some other value”}
irb(main):008:0> testhash.update secondhash
=> {“some other key”=>“some other value”, “some key”=>“some value”}

thats the behaviour of arrays and I know that I could extend the class
Hash, so that its supported.
I simply want to know if there is a special reason why it is not
supported by default.

I guess it’s that Hash#update is peculiar because it depends on which hash
is updated by the other, which is important if both Hashes share some
keys. Apart from that Hash#+ might be a bit inefficient in situations
where you want to update a Hash via +=.

class Hash
def +(h)
dup.update(h)
end
end

a = {}
b = {}

a += b

in reality:

tmp = a + b

a = tmp

old a is dropped

Kind regards

robert

ts wrote:

“b” == benny linux@marcrenearns.de writes:

thats the behaviour of arrays and I know that I could extend the class
Hash, so that its supported. I simply want to know if there is a special
reason why it is not supported by default.

What do you do if the key exist ?

Array#+ always add elements, with Hash#+ keys will be added only if the
key don’t exist otherwise the old value is replaced.

I have seen this discussion before.

It doesn’t bother me much that keys are replaced. That is the nature of
a Hash, that keys are unique.

What bothers me more: If h2 and h3 have common keys, then
h1 = h2 + h3
is not the same as
h1 = h3 + h2

In other words, I expect + to be commutative always. But probably
someone will now show me a case where it is not in Ruby. :slight_smile:

Hal

First of all, no class has a method “+=”. Instead this is a syntactic
shortcut that transforms “a += b” into “a = a + b” - whatever ‘a’ and ‘b’
are.

ok

I would find it intuitive if I could do something like this

testhash = Hash.new
testhash << {“some key” => “some value”}

There is “update”:

yes, I know, but I thought about syntactic consistency
perhaps I have an interation about differenz objects, some of them are arrays, some are hashs (and I
don’t want to check it all the time)

I guess it’s that Hash#update is peculiar because it depends on which hash
is updated by the other, which is important if both Hashes share some
keys.

but its quite clear: the right hash replaces the entry in the left hash with the same key, just
like update. why inventing a new method name for basically same thing?

Apart from that Hash#+ might be a bit inefficient in situations
where you want to update a Hash via +=.

thats the samething with

teststring = "hello"
teststring += " boys and girls"

vs

teststring << "boys and girls"

so why not having “<<” (without temporary object) and “+” or “+=” (with temporary object) instead of
“update”?

I’m not convinced yet.

In other words, I expect + to be commutative always. But probably
someone will now show me a case where it is not in Ruby. :slight_smile:

  ruby -e 'p [1]+[2]==[2]+[1]'

Guy Decoux

Quoteing hal9000@hypermetrics.com, on Wed, Jan 28, 2004 at 01:34:36AM +0900:

ts wrote:

Array#+ always add elements, with Hash#+ keys will be added only if the
key don’t exist otherwise the old value is replaced.

I have seen this discussion before.

It doesn’t bother me much that keys are replaced. That is the nature of
a Hash, that keys are unique.

What bothers me more: If h2 and h3 have common keys, then
h1 = h2 + h3
is not the same as
h1 = h3 + h2

In other words, I expect + to be commutative always. But probably
someone will now show me a case where it is not in Ruby. :slight_smile:

% irb
irb(main):001:0> “a” + “b”
=> “ab”
irb(main):002:0> “b” + “a”
=> “ba”
irb(main):003:0> “b” * 3
=> “bbb”
irb(main):004:0> 3 * “b”
TypeError: String can’t be coerced into Fixnum
from (irb):4:in `*’
from (irb):4

I’ve heard this used as an argument that string classes in C++ should
not have “+” - that it doesn’t behave like addition should… (I know
you’re not among that group!). Those arguing this point lost, and now
most people expect any reasonable implementation of a string object to
respond to “+”.

On the other hand, it isn’t as instantly obvious that you can lose data
when you do “addition” on hashes, so maybe it protects us.

Me, I vote it should be added as a standard method to Hash. It’s useful
to those who understand how it works, and it doesn’t have any other
obvious meaning. I.e., it would be hard for somebody to come back and
say “that surprised me, I thought the “+” method would do ???”.

And for those who don’t find it useful… don’t use it!

My 2 cents ($CA) …

Sam

conclusion: no argument against “<<” / “+” for hashs?
and “delete” is even more obscure when we have “-” : e.g.

testhash = {“key” => “value”, “other key” => “other entry”}
otherhash = {“other key” => “other entry”}

testhash - “key” #-> {“other key” => “other entry”}

should delete the entry with the key “key”

testhash - otherhash #-> {}

should delete the corresponding entry as well

I think this is far more intuitive and flexible

···

Am Wed, 28 Jan 2004 01:39:01 +0900 schrieb ts decoux@moulon.inra.fr:

In other words, I expect + to be commutative always. But probably
someone will now show me a case where it is not in Ruby. :slight_smile:

ruby -e ‘p [1]+[2]==[2]+[1]’

Guy Decoux

ts wrote:

“H” == Hal Fulton hal9000@hypermetrics.com writes:

In other words, I expect + to be commutative always. But probably
someone will now show me a case where it is not in Ruby. :slight_smile:

ruby -e ‘p [1]+[2]==[2]+[1]’

Yes, yes. :slight_smile: But at least they have the same contents.

Merci beaucoups, M’sieur Decoux.

Hal

conclusion: no argument against "<<" / "+" for hashs?

Well, it's more : no arguments for Hash#<< and Hash#+

moulon% ruby -e 'p "aa"<<"bb"'
"aabb"
moulon%

moulon% ruby -e 'p ["aa"]<<"bb"'
["aa", "bb"]
moulon%

Now try the same with an Hash (order is given by the hash value, and not
by the last element added)

Guy Decoux

“benny” linux@marcrenearns.de schrieb im Newsbeitrag
news:20040127180844.0b670068@bava.ho…

In other words, I expect + to be commutative always. But probably
someone will now show me a case where it is not in Ruby. :slight_smile:

ruby -e ‘p [1]+[2]==[2]+[1]’

Guy Decoux

conclusion: no argument against “<<” / “+” for hashs?

No. Arguments are:

“+” is inefficient. (same for “-”)

“<<” has usually the semantics that the left side is a collection while
the right side is an element. And since each entry in a Hash needs a key
value pair this could not be done with <<, because “<<” can only have a
single argument. You could only implement << in a way that “h << [key,
value]” would add the pair (key, value), but this is by no means clearer
than “h[key] = value” IMHO.

see Array: [1]<<[2] yields [1,[2]] and not [1,2]

and “delete” is even more obscure when we have “-” : e.g.

testhash = {“key” => “value”, “other key” => “other entry”}
otherhash = {“other key” => “other entry”}

Again, this is not symmetric with other occurences of “-”: left and right
side should be of the same type, at least both should be containers, i.e.
hashes in this case.

testhash - “key” #-> {“other key” => “other entry”}

should delete the entry with the key “key”

testhash - otherhash #-> {}

should delete the corresponding entry as well

What should it do if the Hash contains Hashes as keys? This is highly
ambiguous and not intuitive.

I think this is far more intuitive and flexible

Regards

robert
···

Am Wed, 28 Jan 2004 01:39:01 +0900 > schrieb ts decoux@moulon.inra.fr:

conclusion: no argument against “<<” / “+” for hashs?

Well, it’s more : no arguments for Hash#<< and Hash#+

moulon% ruby -e ‘p “aa”<<“bb”’
“aabb”
moulon%

moulon% ruby -e ‘p [“aa”]<<“bb”’
[“aa”, “bb”]
moulon%

Now try the same with an Hash (order is given by the hash value, and not
by the last element added)

I read somewhere that the result of the “shift” method is unpredictable because there is no fixed
order in hashes so it shouldn’t matter IMHO. or did I get you wrong?

{“a” => “b”} << {“c” => “d”} #-> {“a” => “b”, “c” => “d”}
{“a” => “b”} << “c” #-> error

···

Am Wed, 28 Jan 2004 02:22:05 +0900 schrieb ts decoux@moulon.inra.fr:

Guy Decoux

No. Arguments are:

“+” is inefficient. (same for “-”)

dito with
“string” += “other_string”
but ok, we can skip this

“<<” has usually the semantics that the left side is a collection while
the right side is an element. And since each entry in a Hash needs a key
value pair this could not be done with <<, because “<<” can only have a
single argument.

what about

"a" << "bcd"

or

["a"] << ["b", ["c", "d"], "e"]

?

You could only implement << in a way that “h << [key,
value]” would add the pair (key, value), but this is by no means clearer
than “h[key] = value” IMHO.

  • you can iterate above hashs and arrays without taking care if they are hashs or arrays.
  • you only have to learn one syntax

see Array: [1]<<[2] yields [1,[2]] and not [1,2]

but ‘a’ << “bcd” yields ‘abcd’ and not ‘a"bcd"’

so thats special to the array-class. but it should neccessarily affect hashes.

1 << 3 #-> 8
thats special to the Fixnum class so you have to learn that behaviour anyway

Again, this is not symmetric with other occurences of “-”: left and right
side should be of the same type, at least both should be containers, i.e.
hashes in this case.

I could agree with that. just thought that the second way would be useful (-> delete)

What should it do if the Hash contains Hashes as keys? This is highly
ambiguous and not intuitive.

no, its quite clear: it happens the same thing like

myhash[{“key” => “val”}] = “other_val”

benny

I read somewhere that the result of the "shift" method is unpredictable
because there is no fixed order in hashes so it shouldn't matter
IMHO. or did I get you wrong?

and I hope that you have read that it don't exist a method
Hash#unshift :slight_smile:

Guy Decoux

“benny” linux@marcrenearns.de schrieb im Newsbeitrag
news:20040127192241.26396079@bava.ho…

No. Arguments are:

“+” is inefficient. (same for “-”)

dito with
“string” += “other_string”

Yes.

“<<” has usually the semantics that the left side is a collection
while
the right side is an element. And since each entry in a Hash needs a
key
value pair this could not be done with <<, because “<<” can only have
a
single argument.

what about

“a” << “bcd”

True. String is special with respect to <<.

What should it do if the Hash contains Hashes as keys? This is highly
ambiguous and not intuitive.

no, its quite clear: it happens the same thing like

myhash[{“key” => “val”}] = “other_val”

No, we were talking about “-”: If h is a Hash that contains hashes as
keys like h = { {“foo”=>“bar”} =>1 } then how is “h - x” interpreted if x
is a Hash? It’s ambiguous.

Regards

robert

X-Newsreader: Sylpheed version 0.9.8claws (GTK+ 1.2.10; i386-portbld-freebsd4.9)
Mime-Version: 1.0
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

“b” =3D=3D benny linux@marcrenearns.de writes:
=20
I read somewhere that the result of the “shift” method is unpredictable
because there is no fixed order in hashes so it shouldn’t matter
IMHO. or did I get you wrong?=20
=20
and I hope that you have read that it don’t exist a method=20
Hash#unshift :slight_smile:
=20
=20

it was a german book:

“Programmieren mit Ruby” [Programing with ruby]
Armin R=F6hrl, Stefan Schmiedl, Clemens Wyss
Heidelberg 2002, ISBN 3-89864-151-1

page 47
[translated into my bad english]

Because hashes don’t have a fixed order the result of this method is unpred=
ictable. “delete” on the
other hand permits the deletition of an element with a known key.

I know “unshift” only from php. what do you want to tell me with this state=
ment?
should I better stay programing php?

benny

···

Am Wed, 28 Jan 2004 02:45:51 +0900 schrieb ts decoux@moulon.inra.fr:

Guy Decoux
=20
=20

I wasn’t successful in deleting a key from hash, which is an hash on its own.

h = { {“foo”=>“bar”} =>1 }.delete({“foo”=>“bar”})

doesn’t seem to work. any idea?

if there is no way to delete such a key then there would be no difference to “-” :
in both cases the whole entry would be deleted.

{“foo” => “bar”}.delete(“foo”) = {“foo” => “bar”} - {“foo” => “bar”}

anyway its a very special case to have a key which is a hash, I think. I don’t see where such a
thing would make sense and was suprised that its possible (maybe ruby is the only
language to allow such a thing?).

when I think of a “key” I think of a quick index-like reference to find something quickly.

regards benny

···

Am Wed, 28 Jan 2004 10:27:35 +0100 schrieb “Robert Klemme” bob.news@gmx.net:

No, we were talking about “-”: If h is a Hash that contains hashes as
keys like h = { {“foo”=>“bar”} =>1 } then how is “h - x” interpreted if x
is a Hash? It’s ambiguous.

Regards

robert

benny wrote:

and I hope that you have read that it don’t exist a method=20
Hash#unshift :slight_smile:

I know “unshift” only from php. what do you want to tell me with this state=
ment?
should I better stay programing php?

Notice there is a smiley. Apparently a small joke.

I guess when you said “shift” you meant << (which looks like
the numeric shift operator) rather than the actual method
named shift (whose opposite is unshift).

I think this minor misunderstanding is only the result of
a French person and a German person conversing in English.

Cheers,
Hal

benny wrote:

I wasn’t successful in deleting a key from hash, which is an hash on its own.

h = { {“foo”=>“bar”} =>1 }.delete({“foo”=>“bar”})

doesn’t seem to work. any idea?

if there is no way to delete such a key then there would be no difference to “-” :
in both cases the whole entry would be deleted.

{“foo” => “bar”}.delete(“foo”) = {“foo” => “bar”} - {“foo” => “bar”}

anyway its a very special case to have a key which is a hash, I think. I don’t see where such a
thing would make sense and was suprised that its possible (maybe ruby is the only
language to allow such a thing?).

when I think of a “key” I think of a quick index-like reference to find something quickly.

[dolio 04:59:10 ~]$ cat prac.rb
#!/usr/bin/ruby

a = { 1 => 2 }
b = { a => 3 }

p b

b.delete a

p b

[dolio 04:59:14 ~]$ ./prac.rb
{{1=>2}=>3}
{}

In your test, the { “foo” => “bar” } stored in the first hash wasn’t the
same as the
one you tried to delete later (different objects/ids, same structure).
Hashes for
objects only have to be the same if #eql? returns true between them, and
that’s
not necessarily the case for two structrurally identical hashes (it’s
true only if they’re
the same object).

As I recall, in Python you can only use immutable things as keys to hashes.
However, in Java, for example, you can use any Object, whether it’s a
String or
a Hashtable, so Ruby isn’t alone.

  • Dan

benny wrote:

and I hope that you have read that it don’t exist a method=20
Hash#unshift :slight_smile:

I know “unshift” only from php. what do you want to tell me with this state=
ment?
should I better stay programing php?

Notice there is a smiley. Apparently a small joke.

I guess when you said “shift” you meant << (which looks like
the numeric shift operator) rather than the actual method
named shift (whose opposite is unshift).

no I meant the method “shift” and indeed there is no method “unshift” for hashes (in ruby, in php,
there is).

I refered to the method “shift” because Mr. Decoux stated
“(order is given by the hash value, and not
by the last element added)”

to say that you can’t use << for hashes.

I’m not shure if I got him right. I thought he said

“the order of the new element in the array when using [“a”] << “b” is given by the array , so that
the added element is always the last one. how would that be in a hash, where we have a key?”

and I wanted to tell him

“I always thought the order doesn’t matter in a hash as you can see be the unpredictability of the
result of the method shift.”

I think this minor misunderstanding is only the result of
a French person and a German person conversing in English.

I think its more the aim of minimalistic communication that leads to confusion.

nevertheless my proposal wasn’t {“a” => “b”} << “c => d” (analog to [“a”] << “b” ) but
{“a” => “b”} << {“c” => “d”}

(see my other posting).

and the argument that this would mean another thing than with arrays (adding an association instead
of an element) I think is not so important because, Hash is an other Object than Array and can
handle << in its own useful way (as String and Fixnum also do).

Cheers,
Hal

ps. I saw the smiley just wanted to know if I interpreted the allusion “unshift” the right way.

cheers,

benny

···

Am Wed, 28 Jan 2004 03:45:35 +0900 schrieb Hal Fulton hal9000@hypermetrics.com: