On Sun, Feb 3, 2013 at 3:05 AM, Marc H. [email protected]
wrote:
Yes, I just tested in IRB:
All my examples were first run through IRB.
I believe this is a design decision.
I’d say it’s a backwards-compatibility decision, to make sure both
ways still work and not needlessly breaking old code.
Internally, ruby will ALWAYS treat the new
hash syntax as the old hash syntax! So I
recommend to use the old hash syntax, your
brain will be happier in the long run.
Not a chance. I much prefer the new way. My brain is quite happy TYVM.
What you answered was none of what I was actually asking for.
…And I really think I demonstrated I knew how splat works…
What I’d like is a DRY and functional way to do this.
The question is really, how can I convert an array that may contain
[‘a’, ‘b’, {:third => ‘c’}] to {:first => ‘a’, :second => ‘b’, :third
=> ‘c’}, plus all other variants of that first form, to the same
final form, as an arguments hash, in an elegant, functional fashion. I
can do it, but it doesn’t feel elegant this way.
And there is a way to convert the last form as well:
foo(({z: 1, x: 2}), ‘bazinga!’, third: 17) comes into *args as:
=> [{:z=>1, :x=>2}, “bazinga!”, {:third=>17}]
brute force conversion:
def splatargdeflate(args,argnames)
return args unless args.is_a?(Array)
return args if args.length < 1
if args.last.is_a?(Hash)
last_arg = args.pop
else
last_arg = {}
end
arg_hash={}
argnames.each_index do |i|
arg_hash[argnames[i]] = args.shift
end
arg_hash.merge!(last_arg)
args.unshift arg_hash
end
def foo(*args)
args = splatargdeflate(args,[:first, :second, :third])
puts args.inspect
end
Here’s the output for the example foo call from above:
puts foo(({z: 1, x: 2}), ‘bazinga!’, third: 17)
=> [{:first=>{:z=>1, :x=>2}, :second=>“bazinga!”, :third=>17}]
And here’s some more, to compare:
puts foo
=> []
puts foo(1)
=> [{:first=>1, :second=>nil, :third=>nil}]
puts foo(1,2)
=> [{:first=>1, :second=>2, :third=>nil}]
puts foo(‘a’, ‘b’, ‘c’)
=> [{:first=>“a”, :second=>“b”, :third=>“c”}]
puts foo(‘a’, ‘b’, third: ‘blah’)
=> [{:first=>“a”, :second=>“b”, :third=>“blah”}]
puts foo(‘a’, ‘b’, first: ‘butno’)
=> [{:first=>“butno”, :second=>“b”, :third=>nil}]
puts foo(nil, nil, nil)
=> [{:first=>nil, :second=>nil, :third=>nil}]
puts foo(1,2,3,4,5,6,7,8,9,10)
=> [{:first=>1, :second=>2, :third=>3}, 4, 5, 6, 7, 8, 9, 10]
And, for more amusement:
foo 1, 2, 3, 4, 5, 6, 7, 8, 9, first: ‘zip’, bazinga: ‘owie’
=> [{:first=>“zip”, :second=>2, :third=>3, :bazinga=>“owie”}, 4, 5, 6,
7, 8, 9]
The thing I really dislike about splatargsdeflate, and why I was
asking in the first place, is that it seems so procedural and as I
said above, brute force. I really wanted something much more
functional.
I’m just wondering if there’s is some cool ruby method that does
something akin to this already that I haven’t discovered, or if it is
something that can be map/reduced somehow. The only place I can see
doing that is in the loop through the argnames:
arg_hash = argnames.reduce(h={}){|h,n| h[n]=args.shift;h}
produces the same arg_hash, at some cost of readability, perhaps.
Anyway, thanks for your time and looking.