Ruby trunk - Feature #6225

Ruby trunk - Feature #6225
Hash#+
03/30/2012 08:19 AM - trans (Thomas Sawyer)
Status:
Rejected
Priority:
Normal
Assignee:
matz (Yukihiro Matsumoto)
Target version:
next minor
Description
Strings and Arrays can be combined with #+. I don't see any reason not to allow Hashes to do so as well.
class Hash
alias :+ :merge
end
Related issues:
Duplicated by Ruby trunk - Feature #9778: Bring shortcut methods to Hash
Rejected
04/27/2014
History
#1 - 03/30/2012 08:36 AM - mame (Yusuke Endoh)
- Assignee set to matz (Yukihiro Matsumoto)
- Status changed from Open to Assigned
Both String#+ and Array#+ delete no information, but
Hash#merge deletes duplicate fields.
I have heard it is the reason, if I recall.
-Yusuke Endoh [email protected]
#2 - 03/30/2012 09:39 AM - rosenfeld (Rodrigo Rosenfeld Rosas)
This argument really doesn't buy me. Groovy allows: [key1: 'value1', another: 1] + [key2: 'value2', another: 2] == [key1: 'value1', another: 2, key2:
'value2'].
I think this is pretty readable as + is also used to denotate unions. I don't think anyone would expect any behavior different from that.
Maybe someone could argue that the result could also mean [key1: 'value1', another: [1, 2], key2: 'value2'] but I think that would be really strange.
#3 - 03/30/2012 11:30 AM - shyouhei (Shyouhei Urabe)
I object. No binary operations shall be called + unless the operation is symmetric.
For historical reasons there are some asymmetric +s in Ruby, but that is not a indulgence for you to add more.
#4 - 03/30/2012 11:42 AM - rosenfeld (Rodrigo Rosenfeld Rosas)
In other words you don't like that {a: 1} + {a: 2} != {a: 2} + {a: 1}
But I really think programming is different from mathematics and I don't think that the fact that a + b != b + a would be enough reason for avoiding the
convenient operator por "b merged to a" (a + b).
Not that I really do care that much about this feature request as I don't see any problem on writing a.merge(b) anyway... I just don't see any problems
06/18/2017
1/8
either for having "a + b == a.merge(b)".
#5 - 03/30/2012 11:46 AM - trans (Thomas Sawyer)
No binary operations shall be called + unless the operation is symmetric.
Why?
Also what do you mean by symmetric? Do you mean commutative? I point out that neither Array#+ or String#+ is really commutative either because
order is significant.
Also, I don't know why you say "indulgence". It's a simple convenience as a means of writing concise, yet readable, code.
#6 - 03/30/2012 12:07 PM - shyouhei (Shyouhei Urabe)
Sorry for my bad English, I didn't intend to attack you.
Anyway there has been a long discussion around +s in programming languages. For instance Perl uses dot to concatenate strings and avoid +s to
concatenate strings and/or arrays. I see they are much more mature than us in this area. Functional languages like Haskell also avoid defining +
onto non-abelian groups.
#7 - 03/30/2012 03:02 PM - duerst (Martin Dürst)
In common sense, * is also commutative. But of course, for matrix multiplication, it's not.
Also, + is used in many fields of mathematics. I'm not a mathematician, but I very strongly doubt that it's commutative in all these cases. (see e.g.
http://arxiv.org/abs/1003.2081 for an example)
What's much more important is whether the + for Hash fits the general image a Ruby programmer has for +. I'm not exactly sure about this, but the
parallel with Array is not too bad.
#8 - 03/30/2012 04:55 PM - matz (Yukihiro Matsumoto)
I myself do not care whether + to be symmetric or not. I care about key conflict.
Since conflicting cause value lost, I am not positive about making + alias to #merge.
Matz.
#9 - 03/30/2012 05:55 PM - naruse (Yui NARUSE)
shyouhei (Shyouhei Urabe) wrote:
Anyway there has been a long discussion around +s in programming languages. For instance Perl uses dot to concatenate strings and avoid +s
06/18/2017
2/8
to concatenate strings and/or arrays. I see they are much more mature than us in this area. Functional languages like Haskell also avoid
defining + onto non-abelian groups.
On Perl, it is because for
perl -e'print "1" + "2"' #=> 3
perl -e'print "1" . "2"' #=> 12
Not because of symmetry.
#10 - 04/08/2012 12:54 PM - jacksonwillis (Jackson Willis)
Would it be better to use Hash#<< instead of Hash#+?
#11 - 04/12/2012 11:36 PM - trans (Thomas Sawyer)
@jacksonwillis #<< makes sense as an alias for #update, not #merge. However I use Hash#<< with this meaning:
def <<(array)
raise if array.size != 2
self[array.first] = array.last
end
There are historical reasons for that definition. But the two can be combined:
def <<(object)
case object
when Array
raise if object.size != 2
self[object.first] = object.last
else
update(object)
end
end
06/18/2017
3/8
#12 - 04/13/2012 04:00 AM - alexeymuranov (Alexey Muranov)
Martin, in math, it is common to use * for both commutative and non-commutative operations but + for only commutative.
But i am more in favor of Matz's argument, because i didn't bother myself about the fact that string addition is non-commutative.
duerst (Martin Dürst) wrote:
In common sense, * is also commutative. But of course, for matrix multiplication, it's not.
Also, + is used in many fields of mathematics. I'm not a mathematician, but I very strongly doubt that it's commutative in all these cases. (see
e.g. http://arxiv.org/abs/1003.2081 for an example)
What's much more important is whether the + for Hash fits the general image a Ruby programmer has for +. I'm not exactly sure about this, but
the parallel with Array is not too bad.
#13 - 04/13/2012 05:27 AM - alexeymuranov (Alexey Muranov)
How about Hash#| for Hash#reverse_merge, and Hash#|= for Hash#reverse_merge! from Rails? (Instead of #+ for #merge.)
I would like to give an algebraic counterpart to Matz's objection: #merge is not injective in the first argument, nor in the second: a.merge(b) ==
a.merge(c) does not imply b == c, but most uses of #+ are injective in each of the arguments.
I know that Set#+ is already an exception to this rule. It seems that it is equivalent to Set#|, isn't it? However, this could be more of a poor definition of
Set#+ than a justification to allow Hash#+ to be a synonym for #merge. I was just looking through "Lectures on ergodic theory" by P. Halmos, and
there the + for sets is used to denote the symmetric difference (as i would expect).
Edited 2013-01-24.
#14 - 10/25/2012 03:51 PM - naruse (Yui NARUSE)
- Target version changed from 2.0.0 to next minor
#15 - 08/07/2013 03:22 AM - zzak (Zachary Scott)
To put an end to the bikeshedding, and because I'd like this ticket to get a resolution:
The original request was to alias Hash#+ to Hash#merge.
matz, if you can make a decision on this alias it would be appreciated!
To all other requests for Hash, aliases and other methods please open a new ticket.
06/18/2017
4/8
#16 - 08/07/2013 10:50 PM - alexch (Alex Chaffee)
Operator overloading is for convenience and to "least surprise". Since + puts two numbers together, and + puts two strings together, and + puts two
arrays together, + should also put two hashes together -- in the way that makes the most sense for each type.
#17 - 08/08/2013 12:45 AM - mame (Yusuke Endoh)
zzak (Zachary Scott) wrote:
matz, if you can make a decision on this alias it would be appreciated!
matz explicitly said that he was not positive:
https://bugs.ruby-lang.org/issues/6225#note-8
So it is reasonable to look for other aliases.
BTW, I don't think that Hash#merge is so frequently-used operation enough to have such a short notation.
I guess we may want it only when the values is not important, that is, when the hash is used like a set. In this case, we can use set.rb which provides
Set#+.
Yusuke Endoh [email protected]
#18 - 08/08/2013 03:40 AM - jimweirich (Jim Weirich)
mame (Yusuke Endoh) wrote:
BTW, I don't think that Hash#merge is so frequently-used operation enough to have such a short notation.
I guess we may want it only when the values is not important, that is, when the hash is used like a set. In this case, we can use set.rb which
provides Set#+.
I use Hash#merge a lot in a Rails project to manage valid attributes for testing scenarios. E.g. valid_default_attributes.merge(overriding_attributes).
-- Jim Weirich
06/18/2017
5/8
#19 - 08/08/2013 09:45 AM - alexeymuranov (Alexey Muranov)
There is another proposition, but for #reverse_merge: #7739.
Another relevant proposal: #7738.
#20 - 08/10/2013 09:36 AM - drbrain (Eric Hodel)
At DevelopersMeeting20130809 matz said:
17:26 charliesome: So it's rejected?
17:29 matz: I guess so.
17:29 matz: I still concern about merge is not a mere addition
So if the original reporter still wishes to make this a feature please make a slide with a short justification and a few examples for the next meeting.
#21 - 08/10/2013 02:31 PM - trans (Thomas Sawyer)
So if the original reporter...
That would be me, but I am not going to make a slide. Some one else can if they like. Personally I think it's obvious. #merge is one of the most
commonly used methods of Hash, so having an operator for it, if at all possible, is a no-brainer in my opinion. Given the options, what other operator
even comes close in meaning more so than #+? So merge is not commutative. Big deal. Technically neither is String#+.
#22 - 08/10/2013 02:41 PM - charliesome (Charlie Somerville)
I think what matz means by "not a mere addition" is that in the cases of String#+ and Array#+, both operands are wholly represented by the result.
In Hash#merge, the return value might not be made up of whole of both operands. So it's not really an addition. IMO Hash#| might be appropriate, but
I don't want to enter into a bikesheddy argument here.
#23 - 08/10/2013 02:43 PM - charliesome (Charlie Somerville)
- Status changed from Assigned to Rejected
Also, since this specific feature (Hash#+) has been rejected by matz, I'm marking this ticket as rejected.
#24 - 08/10/2013 08:56 PM - rosenfeld (Rodrigo Rosenfeld Rosas)
I agree that the operation not being an addition is not a big deal. No one would expect it from a Hash. Groovy does have this operator working exactly
as a merge and I don't see anyone complaining about it. But I don't see any problems either with calling it #|. I would be fine with either "hash +
06/18/2017
6/8
another_hash" or "hash | another_hash" as an alias for hash.merge(another_hash).
As a side note, yesterday I missed a method to perform Array#| in a way that work directly in the array (like #|! if it was possible). I had a code similar
to this:
dependencies = Thread.current[:_my_app_dependencies]
dependencies |= new_dependencies # won't work as expected, of course, since I wanted to store it under Thread.current[:_my_app_dependencies]
But as I said, this is just an aside note, not related to this ticket.
#25 - 08/10/2013 08:58 PM - rosenfeld (Rodrigo Rosenfeld Rosas)
Charlie, any chances to reopen this ticket so that Matz could evaluate the usage of using | instead of +?
#26 - 08/11/2013 09:07 AM - nobu (Nobuyoshi Nakada)
I think new method proposal should be a new ticket.
#27 - 08/13/2013 06:26 AM - alexeymuranov (Alexey Muranov)
A use of Hash#| is proposed in #7739.
There is however a typo in the proposal: it should be
{ :a => 1, :b => 2 } | { :b => 1, :c => 2 } # => { :a => 1, :b => 2, :c => 2 }
#28 - 08/13/2013 05:19 PM - alexeymuranov (Alexey Muranov)
Just a thought about Hash#+: maybe it can be used for merging only hashes with disjoint sets of keys, and return nil otherwise?
#29 - 08/13/2013 05:38 PM - matz (Yukihiro Matsumoto)
I can imagine that would cause serious confusion among users. Raising exception might be better (but only just).
Matz.
#30 - 08/13/2013 11:40 PM - sikachu (Prem Sichanugrist)
I think this operator is really doesn't fit for Hash operation. While in a glance it might make sense, using #merge like what we're doing right now
actually make more sense when you see the code. You're merging two hashes (dictionaries) together, not adding one hash (dictionary) to the other.
#31 - 04/28/2014 01:55 AM - nobu (Nobuyoshi Nakada)
- Related to Feature #9778: Bring shortcut methods to Hash added
06/18/2017
7/8
#32 - 04/28/2014 01:56 AM - nobu (Nobuyoshi Nakada)
- Related to deleted (Feature #9778: Bring shortcut methods to Hash)
#33 - 04/28/2014 01:56 AM - nobu (Nobuyoshi Nakada)
- Duplicated by Feature #9778: Bring shortcut methods to Hash added
06/18/2017
8/8