see the following codes pls, I wonder if this’s a intent or a bug. For
me the first line sounds better having same result with the later line
[1].inject(Hash.new {[]}){ |result, i| result[:mem] << i; result }
=> {}
[1].inject(Hash.new {[]}){ |result, i| result[:mem] <<= i; result }
=> {:mem=>[1]}
P.S. coding with ruby 1.9.2p180 atm
aaron
April 25, 2011, 1:51pm
2
Hi Aaron
2011/4/25 Aaron [email protected] :
see the following codes pls, I wonder if this’s a intent or a bug. For me the
first line sounds better having same result with the later line
[1].inject(Hash.new {[]}){ |result, i| result[:mem] << i; result }
=> {}
[1].inject(Hash.new {[]}){ |result, i| result[:mem] <<= i; result }
=> {:mem=>[1]}
It’s the expected behaviour. See
class Hash - RDoc Documentation .
“If a block is specified, it will be called with the hash object and
the key, and should return the default value. It is the block‘s
responsibility to store the value in the hash if required.”
[1].inject(Hash.new {|h,k| h[k] = Array.new}){ |result, i|
result[:mem] << i; result }
=> {:mem=>[1]}
aaron
April 25, 2011, 2:19pm
3
Hi,
I still cannot understand.
In the first example, result[:mem] should be [ ] before “result[:mem] <<
i” is
executed. Afterwards it should be [1], and the return value should be
{:mem =>
[1]}.
In the second example, what does “<<=” stand for?
Roy
aaron
April 25, 2011, 2:31pm
4
@Roy
<<= should behave like +=, -= etc
aaron
April 25, 2011, 2:25pm
5
Thanks a lot
kind of clear now, so my code’s problem is Hash.new{[]} didn’t store the
array object into the Hash
aaron
April 25, 2011, 8:44pm
6
On Apr 25, 2011, at 8:25 AM, Aaron wrote:
Thanks a lot
kind of clear now, so my code’s problem is Hash.new{[]} didn’t store
the array object into the Hash
If you want the value stored, you need to do it yourself:
[1].inject(
Hash.new{|h,k|h[k]=[]}
){ |result, i| result[:mem] << i;
result }
=> {:mem=>[1]}
-Rob
Rob B.
[email protected] http://AgileConsultingLLC.com/
[email protected] http://GaslightSoftware.com/
aaron
April 26, 2011, 10:11am
7
@Rob thanks
I thought Hash.new{[]} was shortcut for Hash.new{|h,k|h[k]=[]}
aaron
April 26, 2011, 3:05pm
8
On Apr 26, 2011, at 4:10 AM, Aaron wrote:
@Rob thanks
I thought Hash.new{[]} was shortcut for Hash.new{|h,k|h[k]=[]}
The block form is executed when the requested key does not exist. It
makes each call a new array (which is then thrown away).n
irb> answer = [1,4,9].inject(Hash.new {[]}){ |result, i| result[:mem]
<< i; result }
=> {}
irb> answer[:mem]
=> []
irb> answer[:foo]
=> []
The non-block form makes a single array the default for all keys. The
resulting hash still has no entries, but if you ask for any key that
doesn’t exist, you’ll get the (one) default value back. That default
value is a true object that is modified by the << each time the inject
block is executed.
irb> answer = [1,4,9].inject(Hash.new([])){ |result, i| result[:mem]
<< i; result }
=> {}
irb> answer[:mem]
=> [1, 4, 9]
irb> answer[:foo]
=> [1, 4, 9]
Even though your question was for ruby 1.9, the same behavior is found
in 1.8.
-Rob
Rob B.
[email protected] http://AgileConsultingLLC.com/
[email protected] http://GaslightSoftware.com/