Hash Destructuring

hash destructuring ruby
ruby yield hash
ruby hash
ruby hash#to_proc
ruby keyword arguments splat
ruby tricks
in ruby
hash argument

You can destructure an array by using the splat operator.

def foo arg1, arg2, arg3
  #...Do Stuff...
end
array = ['arg2', 'arg3']
foo('arg1', *array)

But is there a way to destruct a hash for option type goodness?

def foo arg1, opts
  #...Do Stuff with an opts hash...
end
opts = {hash2: 'bar', hash3: 'baz'}
foo('arg1', hash1: 'foo', *opts)

If not native ruby, has Rails added something like this?

Currently I'm doing roughly this with

foo('arg1', opts.merge(hash1: 'foo'))

Yes, there is a way to de-structure a hash:

def f *args; args; end
opts = {hash2: 'bar', hash3: 'baz'}
f *opts  #=> [[:hash2, "bar"], [:hash3, "baz"]]

The problem is that you what you want is actually not de-structuring at all. You’re trying to go from

'arg1', { hash2: 'bar', hash3: 'baz' }, { hash1: 'foo' }

(remember that 'arg1', foo: 'bar' is just shorthand for 'arg1', { foo: 'bar' }) to

'arg1', { hash1: 'foo', hash2: 'bar', hash3: 'baz' }

which is, by definition, merging (note how the surrounding structure—the hash—is still there). Whereas de-structuring goes from

'arg1', [1, 2, 3]

to

'arg1', 1, 2, 3

Destructured Hash Assignment (or: Wherein ES6 out-Rubys Ruby), Ruby is usually syntactic sugar city. It's one of the reasons its users love it, how elegant its methods tend to be. We can call .first to get the first item in an array  The destructuring assignment syntax is a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables. The source for this interactive example is stored in a GitHub repository.

It's 2018 and this deserves an update. Ruby 2.0 introduced keyword arguments and with that also the hash splat operator **. Now you can simply do the following:

def foo arg1, opts
  [arg1, opts]
end

opts = {hash2: 'bar', hash3: 'baz'}
foo('arg1', hash1: 'foo', **opts)
#=> ["arg1", {:hash1=>"foo", :hash2=>"bar", :hash3=>"baz"}]

Destructuring Methods in Ruby - Ruby Inside, Hash) object else arguments.map { |a| [a, object.public_send(a)] }.to_h end method_proc.call(values) } destructure is merely a method which takes in a Symbol: the closest you can get to hash destructuring is via block params: { a: 1 , b: 2 }. tap do | a :, b :| end but unfortunately this has its own issues ( #11048 ), it's too strict about missing/extra keys, which doesn't make sense since blocks are intended to be looser with parameter binding.

There is no such thing (although it has been proposed). Since this will change the parsing rule, it cannot be implemented within Ruby. The best I can think of is to define * on hash like

class Hash; alias :* :merge end

and use it in one of the following ways:

foo('arg1', {hash1: 'foo'}*opts)
foo('arg1', {hash1: 'foo'} *opts)
foo('arg1', {hash1: 'foo'}. *opts)

the last of which I think is reasonably close to what you wanted.

Destructuring with Ruby – sarbada, We can also destructure hashes in a very interesting way. A Ruby Hash has a method called values_at that takes a list of keys and returns the  Destructuring Hashes. Thus far, we have only talked about destructuring arrays. We can also destructure hashes in a very interesting way. A Ruby Hash has a method called values_at that takes a list of keys and returns the values for those keys in th order they were given. Check it out.

If you're ok with using active_support:

require 'active_support/core_ext/hash/slice.rb'

def foo(*args)
  puts "ARGS: #{args}"
end

opts = {hash2: 'bar', hash3: 'baz'}
foo *opts.slice(:hash2, :hash3).values

...or you could monkey-patch your own solution:

class Hash
  def pluck(*keys)
    keys.map {|k| self[k] }
  end
end

def foo(*args)
  puts "ARGS: #{args}"
end

opts = {hash2: 'bar', hash3: 'baz'}
foo *opts.pluck(:hash2, :hash3)

stupid ruby tricks, Destructuring yielded arrays This doesn't seem to work nicely (in 1.8.7 at least) for Hashes, though. The Hash#new method with a block. Common Lisp hash table destructuring utils. Contribute to rplacaman/cl-hash-table-destructuring development by creating an account on GitHub.

Feature #8895: Destructuring Assignment for Hash, Given Ruby already supports destructuring assignment with Array (a, b = [1, 2]), I propose destructuring assignments for Hash. Definition of a Method. The first trick involved actually defining the method, as seen in the first part of the article: In newer versions of Ruby, the defining of a method returns the method name as a Symbol: destructure is merely a method which takes in a Symbol: But what exactly it’s doing with that name, now that’s another matter entirely.

Destructuring assignment, Destructuring also works great with complex functions that have a lot of parameters, default values, and so on. Array destructuring. An example of  This behaves just like the dig methods in Array, Hash, and Struct allowing ALL objects to be destructured. The implementation simply uses send to pass valid method calls thru to objects recursively.

Destructuring assignment, The destructuring assignment syntax is a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects,  The destructuring can be used in any of the binding forms ( let, loop, binding, etc) as well as funcation’s parameters and return values. Now that we understand what destructuring is, we can explore in which ways we can use it to simplify our code.

Comments
  • If you are talking about default option, yes merge is the way to go.
  • Is there any reason that you reversed the order instead of doing {hash1: 'foo'}.merge(opts)?
  • @sawa Not really. Just what came out naturally.
  • Well, did this answer your question? Don’t forget to upvote/accept answers to your questions :)
  • Keep in mind that this only works with symbol keys. {**{a: 1}, **{b: 2}} #=> {:a=>1, :b=>2} while {**{'a' => 1}, **{'b' => 2}} #=> TypeError (wrong argument type String (expected Symbol))
  • Perhaps using + instead of * would make more sense?
  • @AndrewMarshall I agree with that. I wanted to make it look close to the splat operator.