emmanuel/virtus — comment on commit cd2b49a5153dbc73f30cca55268ba8a82b76e522
File: lib/virtus/support/options.rb line 19
By emmanuel:

Indeed, I've seen `Enumerable#each_with_object` once or twice before, but not often. So we Rubyists are stuck between explicitly returning the memo in the block or using a somewhat obscure API to avoid the explicit return. I wish there was a `Hash#set` method that returned the receiver; that would make many uses of `Enumerable#inject` clearer and simpler (also it would be a proper command).

Anyhow, this is clearly a style issue, and the title/commit message is meant tongue-in-cheek. I've noticed this 'initialize memo then iterate over collection and conditionally capture value in memo' (aka, use `Enumerable#each` with explicit state instead of `Enumerable#inject`) in many places in dm-core and other dm-related gems, so I when I saw this pattern in Virtus I wanted to spark a discussion about why not use `Enumerable#inject`.

I don't have a strong preference between `Enumerable#each_with_object` and `Enumerable#inject`, but I think strongly prefer one of the two over an external memo.

On Dec 26, 2011, at 7:45 PM, Dan Kubb wrote:

> Another nice idiom is:
>
> ```ruby
> def options
> accepted_options.each_with_object({}) do |name, options|
> value = send(name)
> options[name] = value unless value.nil?
> end
> end
> ```
>
> `Enumerable#each_with_object` is like `Enumerable#inject` except that it always returns the memo object. It works especially well in this case where we only want to conditionally set a value, and it avoids the need to specify the memo so it will be used in the next loop.
>
> IMHO the semantics of this method are probably clearer than inject, even though it's less often seem, which is a shame.
>
> ---
> Reply to this email directly or view it on GitHub:
> https://github.com/emmanuel/virtus/commit/cd2b49a5153dbc73f30cca55268ba8a82b76e522#commitcomment-821402