From: Fuad Saud <fuadksd@...>
Date: 2013-08-17T17:55:17-03:00
Subject: [ruby-core:56702] Re: [ruby-trunk - Feature #8772] Hash alias #| merge, and the case for Hash and Array polymorphism

--001a11c39198aef06804e42aecaa
Content-Type: text/plain; charset=ISO-8859-1

I don't think merge shoud be responsible for handling special cases like
the array. You really should convert the array to a hash before.

If you need to use such thing as reverse_merge!, why not use it like this:

user_opts |= defaults

being "|" an alias for anon destructive reverse_merge? I don't like havin
"|" as a destructive operator.

As for new operators, reverse_merge would be better represented as >>, but
I don't think that's going to be approved.

I'd still stick with << aliased to merge!, but | to reverse_merge is
interesting as well.
On Aug 17, 2013 4:32 PM, "alexeymuranov (Alexey Muranov)" <
redmine@ruby-lang.org> wrote:

>
> Issue #8772 has been updated by alexeymuranov (Alexey Muranov).
>
>
> trans (Thomas Sawyer) wrote:
> > Actually I think #<< is good too. But it's definition needs to be a bit
> more flexible than just merge. That's because it needs to do this:
> >
> >   h = {}
> >   h << [:a,1]
> >   h << [:b,2]
> >   h  #=> {:a=>1, :b=>2}
>
> Thomas, why h[:a] = 1, h[:b] = 2 wouldn't work for you? Or h << [[:a, 1],
> [:b, 2]].to_h (#7292) ?
> ----------------------------------------
> Feature #8772: Hash alias #| merge, and the case for Hash and Array
> polymorphism
> https://bugs.ruby-lang.org/issues/8772#change-41231
>
> Author: trans (Thomas Sawyer)
> Status: Open
> Priority: Normal
> Assignee:
> Category: core
> Target version: current: 2.1.0
>
>
> Ideally Hash and Array would be completely polymorphic in every manner in
> which it is possible for them to be so. The reason for this is very simple.
> It makes a programmer's life easier. For example, in a recent program I was
> working on, I had a list of keyboard layouts.
>
>   layouts = [layout1, layout2, layout3]
>
> Later I realized I wanted to identify them by a label not an index. So...
>
>   layouts = {:foo => layout1, :bar => layout2, :baz => layout3}
>
> Unfortunately this broke my program in a number of places, and I had to go
> through every use of `layouts` to translate what was an Array call into a
> Hash call. If Array and and Hash were more polymorphic I would have only
> had to adjust the places were I wanted to take advantage of the Hash.
> Ideally almost nothing should have actually broken.
>
> The achieve optimal polymorphism between Hash and Array is to treat a
> Hash's keys as indexes and its values as as the values of an array. e.g.
>
>   a = [:a,:b,:c]
>   h = {0=>:a,1=>:b,2=>:c}
>   a.to_a  #=> [:a,:b,:c]
>   h.to_a  #=> [:a,:b,:c]
>
> Of course the ship has already sailed for some methods that are not
> polymorphic, in particular #each. Nonetheless it would still be wise to try
> to maximize the polymorphism going forward. (Perhaps even to be willing to
> take a bold leap in Ruby 3.0 to break some backward compatibility to
> improve upon this.)
>
> In the mean time, let us consider what it might mean for Hash#+ as an
> alias for #merge, *if the above were so*:
>
>   ([:a,:b] + [:c,:d]).to_a             => [:a,:b,:c,:d]
>   ({0=>:a,1=>:b} + {2=>:c,3=>:d}).to_a => [:a,:b,:c,:d]
>
>   ([:a,:b] + [:a,:b]).to_a             => [:a,:b,:a,:b]
>   ({0=>:a,1=>:b} + {0=>:a,1=>:b}).to_a => [:a,:b]
>
> Damn! So it appears that #+ isn't the right operator. Let's try #| instead.
>
>   ([:a,:b] | [:c,:d]).to_a             => [:a,:b,:c,:d]
>   ({0=>:a,1=>:b} | {2=>:c,3=>:d}).to_a => [:a,:b,:c,:d]
>
>   ([:a,:b] | [:a,:b]).to_a             => [:a,:b]
>   ({0=>:a,1=>:b} | {0=>:a,1=>:b}).to_a => [:a,:b]
>
> Bingo. So I formally stand corrected. The best alias for merge is #| not
> #+.
>
> Based on this line of reasoning I formally request the Hash#| be an alias
> of Hash#merge.
>
> P.S. Albeit, given the current state of polymorphism between Ruby's Array
> and Hash, and the fact that it will probably never be improved upon, I
> doubt it really matters which operator is actually used.
>
>
>
> --
> http://bugs.ruby-lang.org/
>

--001a11c39198aef06804e42aecaa
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<p>I don&#39;t think merge shoud be responsible for handling special cases =
like the array. You really should convert the array to a hash before.</p>
<p>If you need to use such thing as reverse_merge!, why not use it like thi=
s:</p>
<p>user_opts |=3D defaults</p>
<p>being &quot;|&quot; an alias for anon destructive reverse_merge? I don&#=
39;t like havin &quot;|&quot; as a destructive operator.</p>
<p>As for new operators, reverse_merge would be better represented as &gt;&=
gt;, but I don&#39;t think that&#39;s going to be approved.</p>
<p>I&#39;d still stick with &lt;&lt; aliased to merge!, but | to reverse_me=
rge is interesting as well.</p>
<div class=3D"gmail_quote">On Aug 17, 2013 4:32 PM, &quot;alexeymuranov (Al=
exey Muranov)&quot; &lt;<a href=3D"mailto:redmine@ruby-lang.org">redmine@ru=
by-lang.org</a>&gt; wrote:<br type=3D"attribution"><blockquote class=3D"gma=
il_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-lef=
t:1ex">
<br>
Issue #8772 has been updated by alexeymuranov (Alexey Muranov).<br>
<br>
<br>
trans (Thomas Sawyer) wrote:<br>
&gt; Actually I think #&lt;&lt; is good too. But it&#39;s definition needs =
to be a bit more flexible than just merge. That&#39;s because it needs to d=
o this:<br>
&gt;<br>
&gt; =A0 h =3D {}<br>
&gt; =A0 h &lt;&lt; [:a,1]<br>
&gt; =A0 h &lt;&lt; [:b,2]<br>
&gt; =A0 h =A0#=3D&gt; {:a=3D&gt;1, :b=3D&gt;2}<br>
<br>
Thomas, why h[:a] =3D 1, h[:b] =3D 2 wouldn&#39;t work for you? Or h &lt;&l=
t; [[:a, 1], [:b, 2]].to_h (#7292) ?<br>
----------------------------------------<br>
Feature #8772: Hash alias #| merge, and the case for Hash and Array polymor=
phism<br>
<a href=3D"https://bugs.ruby-lang.org/issues/8772#change-41231" target=3D"_=
blank">https://bugs.ruby-lang.org/issues/8772#change-41231</a><br>
<br>
Author: trans (Thomas Sawyer)<br>
Status: Open<br>
Priority: Normal<br>
Assignee:<br>
Category: core<br>
Target version: current: 2.1.0<br>
<br>
<br>
Ideally Hash and Array would be completely polymorphic in every manner in w=
hich it is possible for them to be so. The reason for this is very simple. =
It makes a programmer&#39;s life easier. For example, in a recent program I=
 was working on, I had a list of keyboard layouts.<br>

<br>
=A0 layouts =3D [layout1, layout2, layout3]<br>
<br>
Later I realized I wanted to identify them by a label not an index. So...<b=
r>
<br>
=A0 layouts =3D {:foo =3D&gt; layout1, :bar =3D&gt; layout2, :baz =3D&gt; l=
ayout3}<br>
<br>
Unfortunately this broke my program in a number of places, and I had to go =
through every use of `layouts` to translate what was an Array call into a H=
ash call. If Array and and Hash were more polymorphic I would have only had=
 to adjust the places were I wanted to take advantage of the Hash. Ideally =
almost nothing should have actually broken.<br>

<br>
The achieve optimal polymorphism between Hash and Array is to treat a Hash&=
#39;s keys as indexes and its values as as the values of an array. e.g.<br>
<br>
=A0 a =3D [:a,:b,:c]<br>
=A0 h =3D {0=3D&gt;:a,1=3D&gt;:b,2=3D&gt;:c}<br>
=A0 a.to_a =A0#=3D&gt; [:a,:b,:c]<br>
=A0 h.to_a =A0#=3D&gt; [:a,:b,:c]<br>
<br>
Of course the ship has already sailed for some methods that are not polymor=
phic, in particular #each. Nonetheless it would still be wise to try to max=
imize the polymorphism going forward. (Perhaps even to be willing to take a=
 bold leap in Ruby 3.0 to break some backward compatibility to improve upon=
 this.)<br>

<br>
In the mean time, let us consider what it might mean for Hash#+ as an alias=
 for #merge, *if the above were so*:<br>
<br>
=A0 ([:a,:b] + [:c,:d]).to_a =A0 =A0 =A0 =A0 =A0 =A0 =3D&gt; [:a,:b,:c,:d]<=
br>
=A0 ({0=3D&gt;:a,1=3D&gt;:b} + {2=3D&gt;:c,3=3D&gt;:d}).to_a =3D&gt; [:a,:b=
,:c,:d]<br>
<br>
=A0 ([:a,:b] + [:a,:b]).to_a =A0 =A0 =A0 =A0 =A0 =A0 =3D&gt; [:a,:b,:a,:b]<=
br>
=A0 ({0=3D&gt;:a,1=3D&gt;:b} + {0=3D&gt;:a,1=3D&gt;:b}).to_a =3D&gt; [:a,:b=
]<br>
<br>
Damn! So it appears that #+ isn&#39;t the right operator. Let&#39;s try #| =
instead.<br>
<br>
=A0 ([:a,:b] | [:c,:d]).to_a =A0 =A0 =A0 =A0 =A0 =A0 =3D&gt; [:a,:b,:c,:d]<=
br>
=A0 ({0=3D&gt;:a,1=3D&gt;:b} | {2=3D&gt;:c,3=3D&gt;:d}).to_a =3D&gt; [:a,:b=
,:c,:d]<br>
<br>
=A0 ([:a,:b] | [:a,:b]).to_a =A0 =A0 =A0 =A0 =A0 =A0 =3D&gt; [:a,:b]<br>
=A0 ({0=3D&gt;:a,1=3D&gt;:b} | {0=3D&gt;:a,1=3D&gt;:b}).to_a =3D&gt; [:a,:b=
]<br>
<br>
Bingo. So I formally stand corrected. The best alias for merge is #| not #+=
.<br>
<br>
Based on this line of reasoning I formally request the Hash#| be an alias o=
f Hash#merge.<br>
<br>
P.S. Albeit, given the current state of polymorphism between Ruby&#39;s Arr=
ay and Hash, and the fact that it will probably never be improved upon, I d=
oubt it really matters which operator is actually used.<br>
<br>
<br>
<br>
--<br>
<a href=3D"http://bugs.ruby-lang.org/" target=3D"_blank">http://bugs.ruby-l=
ang.org/</a><br>
</blockquote></div>

--001a11c39198aef06804e42aecaa--