How is enum # with_object different from enum # each_with_object?

The documentation says:

enum#each_with_object :-

Iterates the given block for each element with an arbitrary object, obj, and returns obj

enum#with_object:-

Iterates the given block for each element with an arbitrary object, obj, and returns obj

But when I tried below on both constructs, one gave me the result as expected, but the others didn't. Therefore, I suspect there is a difference between the two.

Using each_with_object

%w(foo bar).each_with_object({}) { |str, hsh| hsh[str] = str.upcase }
=> {"foo"=>"FOO", "bar"=>"BAR"}

      

success is here!

Using with_object

%w(foo bar).with_object({}) { |str, hsh| hsh[str] = str.upcase }
 => NoMethodError: undefined method `with_object' for ["foo", "bar"]:Array
    from (irb):1
    from C:/Ruby193/bin/irb:12:in `<main>'

      

failed here!

What is the difference between these two methods?

+3


source to share


2 answers


each

returns an Enumerator object.

%w(foo bar).each.class
=> Enumerator

      

So, for the first case, the array is first converted to Enumerator

, then works on with_object

.



If you want the second case to work, you need to convert the array to an Enumerator. You can use .to_enum

, .each

or .map

to convert an array.

%w(foo bar).map.with_object({}) { |str, hsh| hsh[str] = str.upcase }
=> {"foo"=>"FOO", "bar"=>"BAR"}

      

Read more: Enumerator

+5


source


with object

only works on counters, which means you need to bind it to something that returns it. eg.

%w(foo bar).each.with_object({}) { |str, h| h[str] = str.upcase }

%w(foo bar).detect.with_object(obj) { ... }

      



So, you can call with_object

all that returns an enumerator, if you do not give him a block (eg map

, reduce

, detect

, find_all

...). This includes anything that mixes into an Enumerable .

each_with_object

is essentially an alias for each.with_object

.

+5


source







All Articles