Deep Hash creation one liner

I was trying to create a hash `{ mountain: { river: { tree: 23 } }
}`using the below :

path = [:mountain, :river, :tree,23]
hash = {}
path.each_cons(2).to_a.reverse.inject(hash,:[]=)
# =>
# ~> -:3:in `[]=': wrong number of arguments (1 for 2) (ArgumentError)
# ~> from -:3:in `each'
# ~> from -:3:in `inject'
# ~> from -:3:in `<main>'

I know why the error comes. But my question is - Is there any way to
send 2 arguments to the method `:[]=` ,by breaking the one argument
array using splat or something like that ?

···

--
Posted via http://www.ruby-forum.com/.

You're trying to use a Symbol argument which is a shorthand way to
create a block. If you want to pass more detailed instructions, pass a
block.

Or if you really want, you can redefine :[]=.to_proc.

···

--
Posted via http://www.ruby-forum.com/.

[16] pry(main)> path.reverse.reduce({}){|s,v| v == path.last ? v : {v => s}
}
# => {:mountain=>{:river=>{:tree=>23}}}

···

On Thu, Oct 10, 2013 at 9:58 PM, Love U Ruby <lists@ruby-forum.com> wrote:

I was trying to create a hash `{ mountain: { river: { tree: 23 } }
}`using the below :

path = [:mountain, :river, :tree,23]
hash = {}
path.each_cons(2).to_a.reverse.inject(hash,:=)
# =>
# ~> -:3:in `=': wrong number of arguments (1 for 2) (ArgumentError)
# ~> from -:3:in `each'
# ~> from -:3:in `inject'
# ~> from -:3:in `<main>'

I know why the error comes. But my question is - Is there any way to
send 2 arguments to the method `:=` ,by breaking the one argument
array using splat or something like that ?

--
Posted via http://www.ruby-forum.com/\.

--
Michael Fellinger

You're missing the point.

Using a symbol is a shortcut way to use a predefined block. If you want
a block to do something different, then use a block, not a symbol.

···

--
Posted via http://www.ruby-forum.com/.

Nice solution! It led me to this, which is a little shorter:

    > path = [:mountain, :river, :tree, 23]
     => [:mountain, :river, :tree, 23]
    > path.reverse.reduce { |s,v| {v => s} }
     => {:mountain=>{:river=>{:tree=>23}}}

Quoting from
Module: Enumerable (Ruby 2.0.0) :

    If you do not explicitly specify an initial value for memo,
    then the first element of collection is used as the initial
    value of memo.

Peace,
tiredpixel

···

On 10/10/2013 21:25, Michael Fellinger wrote:

[16] pry(main)> path.reverse.reduce({}){|s,v| v == path.last ? v :
{v => s} } # => {:mountain=>{:river=>{:tree=>23}}}

On Thu, Oct 10, 2013 at 9:58 PM, Love U Ruby <lists@ruby-forum.com > <mailto:lists@ruby-forum.com>> wrote:

I was trying to create a hash `{ mountain: { river: { tree: 23 } }
}`using the below :

path = [:mountain, :river, :tree,23] hash = {}
path.each_cons(2).to_a.reverse.inject(hash,:=) # => # ~> -:3:in
`=': wrong number of arguments (1 for 2) (ArgumentError) # ~>
from -:3:in `each' # ~> from -:3:in `inject' # ~> from -:3:in
`<main>'

I know why the error comes. But my question is - Is there any way
to send 2 arguments to the method `:=` ,by breaking the one
argument array using splat or something like that ?

-- Posted via http://www.ruby-forum.com/\.

-- Michael Fellinger

Joel Pearson wrote in post #1124210:

You're trying to use a Symbol argument which is a shorthand way to
create a block. If you want to pass more detailed instructions, pass a
block.

Or if you really want, you can redefine :=.to_proc.

Yes something like that I also tried,But I also tried..but didn't work.

path = [:mountain, :river, :tree,23]
hash = {}
path.each_cons(2).to_a.reverse.inject(&hash.method(:))
# =>
# ~> -:3:in `': wrong number of arguments (2 for 1) (ArgumentError)
# ~> from -:3:in `each'
# ~> from -:3:in `inject'
# ~> from -:3:in `<main>'

Still I am not being able to pass the 2 arguments,for one argument it
should work. But for 2 argument,I don't know the trick.

···

--
Posted via http://www.ruby-forum.com/\.