Rubynuby - confused by method name "inject"

Ruby’s inject() lets you do amazing things very expressively. I first
got into inject() when realized how easy it makes getting a class by its
fully qualified name:

klass = fully_qualified_name.split(’::’).inject(Module) { |_module,
_symbol|
_module.const_get(_symbol)
}

instance = klass.new

In this example name “inject” totally corresponds to what it is doing
here. To me at least.

Sincerely,
Gennady.

Jeff P. wrote:

As for Inject, nobody has come up with a wording that makes any sense to
me yet. Does Inject have any aliases/synonyms?

How I remember: Inject takes a binary operation (e.g. +) and injects it
between each element of a list.

[1,2,3].inject { |a,b| a+b } => 1+2+3

– Jim W.

On 5/21/06, Jim W. [email protected] wrote:

Jeff P. wrote:

As for Inject, nobody has come up with a wording that makes any sense to
me yet. Does Inject have any aliases/synonyms?

How I remember: Inject takes a binary operation (e.g. +) and injects it
between each element of a list.

[1,2,3].inject { |a,b| a+b } => 1+2+3

Awesome! That really helps me!

Leslie V. wrote:

On 5/21/06, Jim W. [email protected] wrote:

Jeff P. wrote:

As for Inject, nobody has come up with a wording that makes any sense to
me yet. Does Inject have any aliases/synonyms?

How I remember: Inject takes a binary operation (e.g. +) and injects it
between each element of a list.

[1,2,3].inject { |a,b| a+b } => 1+2+3

Awesome! That really helps me!

Seems like “sum” would have been a better name.

Also

[1,2,3].each {|a| b += a}

is easier to read …for me.

Jim W. wrote:

How I remember: Inject takes a binary operation (e.g. +) and injects it
between each element of a list.

[1,2,3].inject { |a,b| a+b } => 1+2+3

– Jim W.

I think about this in a slightly different way, which helps me
rememeber. Something like, “#inject itorates over thie items in order
but also injects the result from the last block call into the current
one.”

(1…5).inject { |injected_value, this_item| injected_value + this_item
} => 15

2006/5/22, Regg Mr [email protected]:

Seems like “sum” would have been a better name.

Definitively not because you can do far more than calculating sums with
inject.

Also

[1,2,3].each {|a| b += a}

is easier to read …for me.

Yes, but it also needs more LOC.

robert

On 5/22/06, Regg Mr [email protected] wrote:

Awesome! That really helps me!

Seems like “sum” would have been a better name.

Or an alias inject_operator perhaps…
This thread has discussed “sum” already and it’s no good because you
can use any operator. I also like “accumulate” as mentioned, but
inject_operator is sooo clear to me.

On 5/22/06, Leslie V. [email protected] wrote:

[1,2,3].inject { |a,b| a+b } => 1+2+3

Awesome! That really helps me!

Seems like “sum” would have been a better name.

Or an alias inject_operator perhaps…
This thread has discussed “sum” already and it’s no good because you
can use any operator. I also like “accumulate” as mentioned, but
inject_operator is sooo clear to me.

…though the other uses of inject defy “inject_operator”…

data = [[1, 7, 3], [1, 2], [1, 5, 4, 1], [1, 8]]

longest_sample = nil
longest_length = data.inject(0) do |accum, sample|
if accum > sample.length
accum
else
longest_sample = sample
sample.length
end
end

puts “Longest sample: #{longest_sample.inspect}, length
#{longest_length}”

…then again, using inject to find longest seems a bit silly…

longest_sample = data[0]
data.each do |sample|
longest_sample = sample if sample.length > longest_sample.length
end
puts “Longest sample: #{longest_sample.inspect}, length
#{longest_length}”

…then again, using inject to find longest seems a bit silly…

longest_sample = data[0]
data.each do |sample|
longest_sample = sample if sample.length > longest_sample.length
end
puts “Longest sample: #{longest_sample.inspect}, length #{longest_length}”

longest_sample = data.max{|a,b| a.length <=> b.length}

Hi –

On Mon, 22 May 2006, Regg Mr wrote:

Awesome! That really helps me!

Seems like “sum” would have been a better name.

Only in the case where you’re calculating a sum :slight_smile: Inject does the
sum-like thing but in a generalized way.

David

This is a question that I have often wondered about and I think this
thread
has gone a fair way to explaining it.

Just to make sure, I want to step through a call to inject (The sum
example)
to see that I have it. Any comments would be great.

[1,2,3].inject(0) { |cur_sum, elem| cur_sum + elem }

Iteration 1
cur_sum = 0, elem = 1
cur_sum = cur_sum + elem #=> cur_sum = 0 + 1 (Replace cur_sum with the
results of the block => 1 )

Iteration 2
cur_sum = 1, elem = 2
cur_sum = cur_sum + elem #=> cur_sum = 1 + 2 (Replace cur_sum with the
results of the block => 3 )

Iteration 3
cur_sum = 3, elem = 3
cur_sum = cur_sum + elem #=> cur_sum = 3 + 3 (Replace cur_sum with the
results of the block => 6 )

Return cur_sum #=> 6

I think that part so far is ok. I get this part. but how would I step
through this?

klass = fully_qualified_name.split(’::’).inject(Module) { |_module,
_symbol|
_module.const_get(_symbol)
}

instance = klass.new

2006/5/22, Daniel N [email protected]:

cur_sum = cur_sum + elem #=> cur_sum = 0 + 1 (Replace cur_sum with the
results of the block => 6 )

Return cur_sum #=> 6

I think that part so far is ok. I get this part. but how would I step
through this?

Exactly the same - only values are different.

klass = fully_qualified_name.split(‘::’).inject(Module) { |_module,
_symbol|
_module.const_get(_symbol)
}

instance = klass.new

class Foo;class Bar;class Baz; end end end
=> nil
“Foo::Bar::Baz”.split(/::/).inject(Object) {|cl,n| print "-> ", cl,
", ", n, “\n”; cl.const_get(n)}.new
→ Object, Foo
→ Foo, Bar
→ Foo::Bar, Baz
=> #Foo::Bar::Baz:0x3a3178

Kind regards

robert

Regg Mr wrote:

Two points:

Seems like “sum” would have been a better name.

Unless the operator isn’t + …

[1,2,3].inject { |left, right| left * right }
  # =>  1*2*3

"A::B".split("::").inject(Object) { |left, right| 

left.const_get(right) }
# => Object.const_get(“A”).const_get(“B”)

(2..n).inject(1) { |left, right| left * right }
  # => n! => 2*3* ... * n

Also

[1,2,3].each {|a| b += a}

is easier to read …for me.

Perhaps, but there is a fundamental difference between the inject and
each versions. The “each” verison is procedural. It defines state (the
value of b) and how that state changes in each iteration (b += a).

The “inject” version is functional. There are no extra state variables
in our code that need initialization. And the expression itself is the
value, rather than having a side effect on a local variable.

Not that one way is better than the other, just noting differences.

– Jim W.

  sample.length

end
end

puts “Longest sample: #{longest_sample.inspect}, length
#{longest_length}”

…then again, using inject to find longest seems a bit silly…

Well, Enumerable#max is the way to go here, but inject isn’t
that clumsy too:

longest = data.inject{|max, this| this.length > max.length ? this : max}
puts “Longest sample: #{longest.inspect}, length #{longest.length}”

I love it, it’s the swiss army knife of Enumerable.

cheers

Simon

On 5/21/06, Logan C. [email protected] wrote:

Epsilon). Calculus and Physics are “twenty some odd years ago” for
me.

I think you mean Sigma. And I believe when you don’t refer to it as
sigma you say “Summation”.

But I am not a mathematician, so take what I said with a grain of salt.

The big Sigma is often called the n-ary sum operator, and there’s a
corresponding big Pi called the n-ary product (it can be implemented
as inject where the operation in the block is *).

So, in math-speak, I think one could say:

inject applies a block pairwise as an n-ary operation over an
Enumerable, with an optional initial value.

This may or may not help anyone understand it. :slight_smile:

-A

“Kroeger, Simon (ext)” [email protected] writes:

Well, Enumerable#max is the way to go here, but inject isn’t
that clumsy too:
longest = data.inject{|max, this| this.length > max.length ? this : max}

longest = data.inject{|max, this| [this.length, max.length].max }

:wink: (That’s how they do it in APL too, btw.)

Christian N. schrieb:

longest = data.inject{|max, this| [this.length, max.length].max }

:wink: (That’s how they do it in APL too, btw.)

I know why I prefer Ruby :wink:

data = %w"hello christian and APL"
p data.inject{|max, this| [this.length, max.length].max }

=> undefined method `length’ for 9:Fixnum (NoMethodError)

Regards,
Pit

On 5/22/06, Farrel L. [email protected] wrote:

…then again, using inject to find longest seems a bit silly…

longest_sample = data[0]
data.each do |sample|
longest_sample = sample if sample.length > longest_sample.length
end
puts “Longest sample: #{longest_sample.inspect}, length #{longest_length}”

longest_sample = data.max{|a,b| a.length <=> b.length}

Yes precisely! That’s what I like about Ruby, everyone’s a smartypants!
(one day I will be too!)

Hi,

On 5/24/06, Pit C. [email protected] wrote:

=> undefined method `length’ for 9:Fixnum (NoMethodError)

This works:
p data.inject(0){|max, this| [this.length, max].max }

And in APL it’s 4 Unicode characters plus the symbol:
(max)(reduce)(shape)(each)data,
where (reduce) is an operator on (max) producing the function which
is equivalent to Ruby’s inject method.

So there … :slight_smile:

Stuart

I must say I’m surprised that my tired old thread is still kicking
around.

If I may summarize, the reason I was confused by Inject is that it is
useful but poorly named.

many thanks for all the replies,
jp