Forum: Ruby rubynuby - confused by method name "inject"

8dad1ec4d769734583f45fbbee5cd009?d=identicon&s=25 Jeff Pritchard (Guest)
on 2006-05-21 04:42
Can anybody explain to me how the Enumberable#inject method is
"injecting" something into something?  I find it very difficult remember
method names when I don't "get" them.  So far in Ruby, "inject" takes
the cake for least understandable method name (with my own particular
convoluted gray matter).

Can somebody give some examples of its use and state in words how it is
"injecting" something into something?

thanks,
jp

P.S.
If anybody wants to take a stab at "collect", that would be welcome
also.
E34b5cae57e0dd170114dba444e37852?d=identicon&s=25 Logan Capaldo (Guest)
on 2006-05-21 04:54
(Received via mailing list)
On May 20, 2006, at 10:42 PM, Jeff Pritchard wrote:

>
> thanks,
> jp
>
> P.S.
> If anybody wants to take a stab at "collect", that would be welcome
> also.
>
> --
> Posted via http://www.ruby-forum.com/.
>

Would you prefer foldl? :-p

Well one possible explanation is that it's injecting the contents of
the array and the result of the last call to the block back into the
block, sort of an auto-transfusion.

The canonical inject example is the sum of the elements of an array:
irb(main):001:0> [1, 7, 2].inject(0) { |sum_so_far, current_item|
sum_so_far + current_item }
=> 10

As far as collect goes, you're collecting the results of the block
applied to each element in the enumerable. (I personally prefer map
to collect as far as terminology goes).

irb(main):002:0> [1, 7, 2].collect { |item| item * 2 }
=> [2, 14, 4]
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2006-05-21 04:58
(Received via mailing list)
Hi --

On Sun, 21 May 2006, Jeff Pritchard wrote:

> jp
>
> P.S.
> If anybody wants to take a stab at "collect", that would be welcome
> also.

I have just about the mental energy for collect right now, so I'll
give that a try :-)

The basic usage (just to have an example):

You have an array:  [1,2,3,4,5]
You call:  new_array = array.collect {|element| element * 10 }
The result (new_array) is: [10,20,30,40,50]

Now, in terms of the word "collect" itself:

Imagine that the elements of the first array are sitting on a bus.
The conductor comes through the bus and *collects* the fare from each
element.  The fare is: yourself times 10.  The cumulative result is a
new array, consisting of the old array's elements but each multiplied
by 10.

So collect is an iterative process, where a new value is "collected"
from each old value, courtesy of being passed to the code block.  The
new array is thus a one-to-one mapping of the old array, with the
values transformed.  (So collect is also called "map" :-)


David
0b561a629b87f0bbf71b45ee5a48febb?d=identicon&s=25 Dave Burt (Guest)
on 2006-05-21 05:08
(Received via mailing list)
Jeff Pritchard wrote:
> Can anybody explain to me how the Enumberable#inject method is
> "injecting" something into something?  I find it very difficult remember
> method names when I don't "get" them.  So far in Ruby, "inject" takes
> the cake for least understandable method name (with my own particular
> convoluted gray matter).
>
> Can somebody give some examples of its use and state in words how it is
> "injecting" something into something?

["foo", "bar"].inject(5) {|total, word| total + word.length } #=> 11

This example injects the result of the block applied to each element of
the collection into a single value.

I actually prefer the Haskell term, "fold" -- it repeatedly folds the
function of the value and an element of the collection back into the
value.

> If anybody wants to take a stab at "collect", that would be welcome
> also.

I use "map", which is an alias of "collect".

ys = xs.map {|x| x * x }

It takes a block (a mapping from X to Y) and applies it to a collection
of Xs to map them to Ys.

Cheers,
Dave
8dad1ec4d769734583f45fbbee5cd009?d=identicon&s=25 Jeff Pritchard (Guest)
on 2006-05-21 07:05
I agree, "map" makes a lot more sense than "collect".  I'm going to just
forget about collect and consider it "personally deprecated due to poor
naming".

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

thanks,
jp

P.S.
If I were to choose a synonym for the "inject" method, I might come up
with "collect".  vis. "iterate over these items and collect the results
in one answer."  It seems to me that this method does the same thing
that the big Latin "E" symbol (Epsilon) does in Mathematics.  Is there a
name for that symbol within the math community?  (I mean - besides
Epsilon).  Calculus and Physics are "twenty some odd years ago" for me.

P.P.S.
Is it considered bad form to create your own aliases for things like
this?  For instance, if I were to create an alias for Enumerated#inject
like "gather", and use that all over my programs, would this be
considered bad form, or just hunky-dory use of the language?
481b8eedcc884289756246e12d1869c1?d=identicon&s=25 Francis Cianfrocca (Guest)
on 2006-05-21 07:16
(Received via mailing list)
I think the name originally came from Smalltalk.
8dad1ec4d769734583f45fbbee5cd009?d=identicon&s=25 Jeff Pritchard (Guest)
on 2006-05-21 07:17
BTW, I think "combine" makes the most sense to me for a synonym of
"inject".  The block describes how to combine all of the elements into a
single answer.  vis:

total_cost = [[pie,2.00],[coffee,1.00]].combine { |cost, [food, price]|
cost += price }


jp
E34b5cae57e0dd170114dba444e37852?d=identicon&s=25 Logan Capaldo (Guest)
on 2006-05-21 07:28
(Received via mailing list)
On May 21, 2006, at 1:05 AM, Jeff Pritchard wrote:

> If I were to choose a synonym for the "inject" method, I might come up
> with "collect".  vis. "iterate over these items and collect the
> results
> in one answer."  It seems to me that this method does the same thing
> that the big Latin "E" symbol (Epsilon) does in Mathematics.  Is
> there a
> name for that symbol within the math community?  (I mean - besides
> 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.
E34b5cae57e0dd170114dba444e37852?d=identicon&s=25 Logan Capaldo (Guest)
on 2006-05-21 07:34
(Received via mailing list)
On May 21, 2006, at 1:17 AM, Jeff Pritchard wrote:

> jp
>
> --
> Posted via http://www.ruby-forum.com/.
>

well here's another suggestion for an alternate name:

each_with_state

We already have each_with_index. Of course this implies an alternate
ordering of the arguments.
75fa5e3b14c68e02e4f5799aa2ec64d1?d=identicon&s=25 Joseph Abrahamson (Guest)
on 2006-05-21 08:02
In Common Lisp there is the reduce function. I think that name
appropriately qualifies the action involved.

(reduce (function +) (list 1 2 3 4 5 6))

(1..6).inject(0) {|c,v| c + v}

Also: yes, the "E" in math is a Sigma or summation. I wouldn't say
they're quite the same since summnation always involves summing whereas
inject/reduce are more abstract and multipurpose.

Ex:
(reduce (function *) (list 1 2 3 4 5 6))
(1..6).ineject(1) {|c,v| c * v}
These both act more like a factorial than a sum.
F0379e983ab499fac4d972494beab5c0?d=identicon&s=25 Brez! !! (brez)
on 2006-05-21 08:28
yea look into the difference between functional / imperative
programming languages / most languages [Java, C, C++, etc] are
imperative.. inject, filter, map, et al are very common place in
functional languages and require a different mindset than their
imperative cousins. obviously ruby [as well as python] have
functional elements. it's worth taking the time to understand
what they do / they're very useful/powerful when dealing with
collections..
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 Joel VanderWerf (Guest)
on 2006-05-21 09:29
(Received via mailing list)
Jeff Pritchard wrote:
> As for Inject, nobody has come up with a wording that makes any sense to
> me yet.  Does Inject have any aliases/synonyms?

You can think of it as "accumulate", since there is an "accumulator",
whose value is initially the argument to inject (or the first value in
the collection), and subsequently the block value.
5d15f83f0e681b138d95f1ec430868fa?d=identicon&s=25 Joey (Guest)
on 2006-05-21 09:33
(Received via mailing list)
[1,2,3,4,5].inject(0){|sum,num|sum+num} => 15
Which is ((((0+1)+2)+3)+4)+5

j`ey
http://www.eachmapinject.com
5da4c52f43677f395aff5bde775593c2?d=identicon&s=25 Daniel Schierbeck (dasch)
on 2006-05-21 11:49
(Received via mailing list)
Jeff Pritchard wrote:
> If anybody wants to take a stab at "collect", that would be welcome

I think #collect is fairly intuitive:

   addresses = contacts.collect{|contact| contact.address}

Here we collect the addresses of the contacts.


Daniel
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2006-05-21 13:17
(Received via mailing list)
Hi --

On Sun, 21 May 2006, Jeff Pritchard wrote:

> P.P.S.
> Is it considered bad form to create your own aliases for things like
> this?  For instance, if I were to create an alias for Enumerated#inject
> like "gather", and use that all over my programs, would this be
> considered bad form, or just hunky-dory use of the language?

It would be bad form, in my opinion.  It's good to discuss what you
feel are the shortcomings of the language in a forum like this, but
don't turn your programs into a position statement at the cost of
making them harder to understand.


David
Ba2582cd50a59359ac3f7305ad2a0429?d=identicon&s=25 ReggW (Guest)
on 2006-05-21 13:30
Jeff Pritchard wrote:
> Can anybody explain to me how the Enumberable#inject method is
> "injecting" something into something?  I find it very difficult remember
> method names when I don't "get" them.  So far in Ruby, "inject" takes
> the cake for least understandable method name (with my own particular
> convoluted gray matter).

I agree!!!!


I have it marked in my "Ruby notes", as "Don't use".
I do this so that when I come across it again, I won't spend 2 hours
trying to make sense out of it's purpose.
8dad1ec4d769734583f45fbbee5cd009?d=identicon&s=25 Jeff Pritchard (Guest)
on 2006-05-21 16:41
Following David's suggestion, I think I'll go ahead and use it, but
always precede it with a comment so I can remember what it does when I
come back to it later.  Something like:

# this "inject" method is "combining" the results from the block
operation into a single answer
[1,2,3,4,5].inject(0){|sum,num|sum+num}


This topic makes me wonder, and perhaps one of the old-timers here can
answer this.  If I understand it correctly, Matz basically "invented"
ruby.  Matz is, as far as I know, Japanese.  Was Ruby first written with
Japanese class and method names and later translated to English?  Or did
it start out in English?

thanks,
jp





ReggW wrote:
> Jeff Pritchard wrote:
>> Can anybody explain to me how the Enumberable#inject method is
>> "injecting" something into something?  I find it very difficult remember
>> method names when I don't "get" them.  So far in Ruby, "inject" takes
>> the cake for least understandable method name (with my own particular
>> convoluted gray matter).
>
> I agree!!!!
>
>
> I have it marked in my "Ruby notes", as "Don't use".
> I do this so that when I come across it again, I won't spend 2 hours
> trying to make sense out of it's purpose.
37a3c73ffbf864e4b28f7f2384ee12ce?d=identicon&s=25 Timothy Hunter (tim-hunter)
on 2006-05-21 17:22
(Received via mailing list)
On May 21, 2006, at 10:42 AM, Jeff Pritchard wrote:

> answer this.  If I understand it correctly, Matz basically "invented"
> ruby.  Matz is, as far as I know, Japanese.  Was Ruby first written
> with
> Japanese class and method names and later translated to English?
> Or did
> it start out in English?
>
> thanks,
> jp

No, Matz has said that he wanted to create a language that could be
used by everybody and he realized that it would have to use English.

Ruby honors its influences by reusing their names. Thus we have the
Smalltalk's "inject", Lisp's "mixin", C's "sprintf" and "puts",
Perl's $ variables, etc.
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2006-05-21 18:02
(Received via mailing list)
2006/5/21, ReggW <me@yourhome.com>:
> I have it marked in my "Ruby notes", as "Don't use".
> I do this so that when I come across it again, I won't spend 2 hours
> trying to make sense out of it's purpose.

Granted that it may take some time to understand it and to recognize
its power (took me a while, too), but - once you grokked it you'll be
amazed how much you can do with it.  A lot - if not all - methods in
Enumerable can be elegantly implemented with inject.  Try it out!
Also, when searching the archives you'll find quite a few postings
that show how something can be done with inject and often it's more
elegant than other methods.  Just compare the example that has been
shown in this thread with the version using each:

sum = 0
enum.each {|x| sum += x}
sum

enum.inject(0) {|sum, x| sum + x}

Kind regards

robert
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2006-05-21 18:08
(Received via mailing list)
Hi --

On Mon, 22 May 2006, Timothy Hunter wrote:

>>
> No, Matz has said that he wanted to create a language that could be used by
> everybody and he realized that it would have to use English.
>
> Ruby honors its influences by reusing their names. Thus we have the
> Smalltalk's "inject", Lisp's "mixin", C's "sprintf" and "puts", Perl's $
> variables, etc.

A dubious honor, in the latter case; quoting the ToDo:

* discourage use of symbol variables (e.g. $/, etc.) in manual
* discourage use of Perlish features by giving warnings.

:-)


David
397f61cc4458e13157b4facf72325e5f?d=identicon&s=25 Gennady Bystritsky (Guest)
on 2006-05-21 18:45
(Received via mailing list)
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.
10d4acbfdaccb4eee687a428ca00a5d8?d=identicon&s=25 Jim Weirich (weirich)
on 2006-05-21 18:55
Jeff Pritchard 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 Weirich
Ad4caa46eebe9347305177fc33468563?d=identicon&s=25 Mike Nelson (miken700)
on 2006-05-21 23:54
Jim Weirich 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 Weirich

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
37ee5fa90f5eaeef62553629382497f7?d=identicon&s=25 Leslie Viljoen (Guest)
on 2006-05-22 11:28
(Received via mailing list)
On 5/21/06, Jim Weirich <jim@weirichhouse.org> wrote:
> Jeff Pritchard 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!
927d7f10fcbcb6b90a0d53047f14ec7b?d=identicon&s=25 Regg Mr (regg)
on 2006-05-22 12:04
Leslie Viljoen wrote:
> On 5/21/06, Jim Weirich <jim@weirichhouse.org> wrote:
>> Jeff Pritchard 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.
37ee5fa90f5eaeef62553629382497f7?d=identicon&s=25 Leslie Viljoen (Guest)
on 2006-05-22 12:16
(Received via mailing list)
On 5/22/06, Regg Mr <spamwhite@cox.net> 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.
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2006-05-22 12:17
(Received via mailing list)
2006/5/22, Regg Mr <spamwhite@cox.net>:
> 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
37ee5fa90f5eaeef62553629382497f7?d=identicon&s=25 Leslie Viljoen (Guest)
on 2006-05-22 13:36
(Received via mailing list)
On 5/22/06, Leslie Viljoen <leslieviljoen@gmail.com> 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}"
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2006-05-22 13:42
(Received via mailing list)
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 :-)  Inject does the
sum-like thing but in a generalized way.


David
05be5d6610e2c3f1780aa0e39e902e93?d=identicon&s=25 Farrel Lifson (Guest)
on 2006-05-22 13:42
(Received via mailing list)
> ..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}
37ee5fa90f5eaeef62553629382497f7?d=identicon&s=25 Leslie Viljoen (Guest)
on 2006-05-22 13:54
(Received via mailing list)
On 5/22/06, Farrel Lifson <farrel.lifson@gmail.com> 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!)
9d1f5d2d9de70bd9a934f557dc95a406?d=identicon&s=25 Daniel ----- (liquid)
on 2006-05-22 13:58
(Received via mailing list)
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
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2006-05-22 15:48
(Received via mailing list)
2006/5/22, Daniel N <has.sox@gmail.com>:
> 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
10d4acbfdaccb4eee687a428ca00a5d8?d=identicon&s=25 Jim Weirich (weirich)
on 2006-05-22 16:01
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 Weirich
87e9a89c53ccf984db792113471c2171?d=identicon&s=25 Kroeger, Simon (ext) (Guest)
on 2006-05-22 16:59
(Received via mailing list)
> 		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
05e48e632fdd0b2c25d27042f52c11d5?d=identicon&s=25 A LeDonne (Guest)
on 2006-05-24 18:24
(Received via mailing list)
On 5/21/06, Logan Capaldo <logancapaldo@gmail.com> 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. :)

-A
7264fb16beeea92b89bb42023738259d?d=identicon&s=25 Christian Neukirchen (Guest)
on 2006-05-24 21:48
(Received via mailing list)
"Kroeger, Simon (ext)" <simon.kroeger.ext@siemens.com> 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 }

;-)  (That's how they do it in APL too, btw.)
93d566cc26b230c553c197c4cd8ac6e4?d=identicon&s=25 Pit Capitain (Guest)
on 2006-05-24 22:08
(Received via mailing list)
Christian Neukirchen schrieb:
>
>   longest = data.inject{|max, this| [this.length, max.length].max }
>
> ;-)  (That's how they do it in APL too, btw.)

I know why I prefer Ruby ;-)

   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
A402df36168b81b31c17adcbb5ae8cf4?d=identicon&s=25 Pistos Christou (pistos)
on 2006-05-24 23:06
A LeDonne wrote:
> 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. :)

Shockingly [to myself], I actually understand that, but I think it
doesn't cover all the possibile uses of inject, some of which are not
"operator in-betweenings".

But thanks for sharing.  Mentally relating product and summation to
inject helps me tolerate what I otherwise think is feasibly the most
unintuitively-named standard method I've ever encountered.

Pistos
39f85b1ab2f9c10f353b77d6b7e1e1c1?d=identicon&s=25 stuart yarus (Guest)
on 2006-05-24 23:44
(Received via mailing list)
Hi,

On 5/24/06, Pit Capitain <pit@capitain.de> 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 ...    :-)

Stuart
8dad1ec4d769734583f45fbbee5cd009?d=identicon&s=25 Jeff Pritchard (Guest)
on 2006-05-25 04:05
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
88521907e2c9c585bc94e35a38893dc5?d=identicon&s=25 Jenda Krynicky (jendaperl)
on 2007-03-01 12:17
Jeff Pritchard wrote:
> 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

The thread is still kicking exactly because names are important. And
when it comes to inventing stupid names Ruby is a professional. inject?
yieiayeld? How the heck is the meaningless nonsense spellllled? Not
speaking about the fact that restiricting (well, almost) the methods to
a single block/closure/function passed is silly, though not as silly as
doing so behind the scenes (not included in the argument list) and
calling it using a silly keyword.
Ec5a599777854c540fd102ef4691fe10?d=identicon&s=25 Rimantas Liubertas (Guest)
on 2007-03-01 12:32
(Received via mailing list)
> The thread is still kicking exactly because names are important. And
> when it comes to inventing stupid names Ruby is a professional.inject?

Don't you confuse "stupid" with "the ones I am not used to"?

> yieiayeld? How the heck is the meaningless nonsense spellllled?

You mean yield? Since when normal English word is meaningless nonsense?

http://dictionary.reference.com/search?q=yield


Regards,
Rimantas
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2007-03-01 12:34
(Received via mailing list)
On 3/1/07, Jenda Krynicky <jenda@cpan.org> wrote:
> The thread is still kicking exactly because names are important. And
>
it is not my style to feed trolls, but I just want to state:

you are polluting this ML
your posts are extremely annoying
I have no way to get rid of your posts without losing potential
information

If your email address is authentic I consider informing CPAN about
your behavior.

Have a nice day.

Robert
Cff9eed5d8099e4c2d34eae663aae87e?d=identicon&s=25 Jacob Fugal (Guest)
on 2007-03-01 17:43
(Received via mailing list)
On 3/1/07, Jenda Krynicky <jenda@cpan.org> wrote:
> The thread is still kicking exactly because names are important. And
> when it comes to inventing stupid names Ruby is a professional. inject?
> yieiayeld? How the heck is the meaningless nonsense spellllled? Not
> speaking about the fact that restiricting (well, almost) the methods to
> a single block/closure/function passed is silly, though not as silly as
> doing so behind the scenes (not included in the argument list) and
> calling it using a silly keyword.

I have to ask, from the apparent bitterness and outright hostility of
your frequent and recent posts -- did a Ruby-programmed DARPA GRand
Challenge[1] contestant run over your puppy?

Jacob Fugal

[1] http://www.darpa.mil/grandchallenge/index.asp
F9bd1f8df35143db8bb314e2732b717c?d=identicon&s=25 Kal Starkis (kal)
on 2014-01-03 16:11
Since this old discussion is one of the top ranking pages when you
Google 'ruby inject' or 'inject method', it's probably worth adding that
since version 1.8.7 Ruby has had the #reduce method, which is an alias
of #inject.

It seems a lot of people prefer #reduce, because it's reducing the list
down to a single value. Personally I think it's just as bad. Another
commenter said, the classic example of #inject is to sum the elements of
an array. So now we have a method called 'reduce' to add elements
together?! One might expect #reduce to work more like #drop or #take or
#select--to create a smaller (reduced) subset. To me it communicates
nothing of the combining nature of the method--unless maybe I think of
it in cooking terms, where one boils a sauce to condense it, but that's
being generous I think.

It's hard to come up with a good short name for such a versatile
function without implying an increase or decrease of successive results.
I think of the word 'cumulative' when I think of how #inject is using
the result of one iteration in the next one, and 'cumulate' is a verb,
but perhaps not a very common one, and it does kind of imply an increase
in successive results. 'Accumulate' is similar.

I wouldn't mind Jeff's suggestion of 'combine', except I think it could
very easily be confused with concatenation methods like #concat and #+,
which combines two arrays into one.

But then we have 'fold', which is the name Wikipedia went with in
categorising these types of functions. Why on earth couldn't Ruby have
gone with this? Like 'reduce', it's used by a stack of other languages,
but unlike 'reduce' it doesn't imply a decrease in value. Check out the
top definitions of the word 'fold' from my dictionary:

fold
verb [ with obj. ]
1 bend (something flexible and relatively flat) over on itself so that
one part of it covers another: Sam folded up the map.
• (fold something in/into) mix an ingredient gently with (another
ingredient), especially by lifting a mixture with a spoon so as to
enclose it without stirring or beating: fold the egg whites into the
chocolate mixture.

So there's that cooking metaphor again. But how elegant is that! No
metaphor is going to be a perfect fit for all that #inject is able to
do, but I reckon #fold would be a thousand times better than #inject and
#reduce.

I'm hoping they'll add #fold as an alias method one day. But until then,
I guess I'll stick with #inject.
1d57c32d7712e7222dbbfdc363473837?d=identicon&s=25 Avdi Grimm (Guest)
on 2014-01-03 17:24
(Received via mailing list)
I find #reduce much better than #inject, but #fold is my preference as
well. Consistent with other languages, and I've always found the
"folding
an ingredient into dough" metaphor apt.

But I can live with #reduce.
9a45896e48a382fe5c656b8873e0dfcb?d=identicon&s=25 Stu (Guest)
on 2014-01-03 17:46
(Received via mailing list)
Fold is actually an older than functional programming concept for
recursive
computation which is just more syntax to the symbolic nature of these
languages. The inverse methods unfold/misfold would be the actual
removal,
deletions or cause for infection. Consider Stanford university's gene
folding distributed computing research project:
http://folding.stanford.edu/

Many programmers come from different languages and have different
preferences to which /tokens/ yield the best value for their current
project. I enjoy using unix style commands like grep and so forth.
Someone
who has a background in either haskall, ocamal erlang or what not may
want
to use fold over reduce or use map or create their own datamapper and
declare their own name for it.

I use fold in my personal scripts. It's really not that difficult to
create
your own. As far as having it in future release of the language the real
question is what would the inverse be misfold or unfold ... or leave the
user to create their own.

Drop the cooking metaphor. It's a biological concept. Consider reading
Alan
Kay for your meta and linguistic concepts.
1d57c32d7712e7222dbbfdc363473837?d=identicon&s=25 Avdi Grimm (Guest)
on 2014-01-03 18:23
(Received via mailing list)
On Fri, Jan 3, 2014 at 11:45 AM, Stu <stu@rubyprogrammer.net> wrote:

> Drop the cooking metaphor. It's a biological concept. Consider reading
> Alan Kay for your meta and linguistic concepts.


This statement amuses me, because Alan Kay was specifically inspired by
biological concepts (cells) when he came up with his conception of OO
:-)
F0987c97234fa9c6b26f796bdbdab037?d=identicon&s=25 Andrew Vit (Guest)
on 2014-01-03 18:42
(Received via mailing list)
Something about "map" + "fold" is pleasantly humorous.
F9bd1f8df35143db8bb314e2732b717c?d=identicon&s=25 Kal Starkis (kal)
on 2014-01-03 18:49
Stu wrote in post #1132133:
> I use fold in my personal scripts. It's really not that difficult to
> create
> your own. As far as having it in future release of the language the real
> question is what would the inverse be misfold or unfold ... or leave the
> user to create their own.
>
> Drop the cooking metaphor. It's a biological concept.

Hey, if the protein folding metaphor works for you, great! Strike up
another reason why 'fold' is a better name than 'inject'!

You lost me though when you started talking about 'fold' and 'reduce' as
two different things. No one here is arguing for a new method. The
thread is about the native #inject method in Ruby, and how that name
doesn't help one intuitively understand or remember what it does.
F9bd1f8df35143db8bb314e2732b717c?d=identicon&s=25 Kal Starkis (kal)
on 2014-01-03 18:55
Andrew Vit wrote in post #1132140:
> Something about "map" + "fold" is pleasantly humorous.

Now that you point that out, indeed it is! There you go, another fine
reason to add #fold.

(I've always preferred #map to #collect.)
F141ba99f29e55f02207f5488fe5ce95?d=identicon&s=25 Dave Aronson (Guest)
on 2014-01-03 20:03
(Received via mailing list)
On Fri, Jan 3, 2014 at 12:49 PM, Kal Starkis <lists@ruby-forum.com>
wrote:

> The thread is about the native #inject method in Ruby, and how that
> name doesn't help one intuitively understand or remember what it does.

It sort of does, if you think of it as *injecting* the method or
block, between the values in the array.  (And between the initial
value, if given, and the array.)  So for instance:

 arr = [1, 2, 3]
 arr.inject(:-)

is like injecting "-" into the spaces between the values 1, 2, 3, so
you get 1, - 2, - 3.  Speaking it with the usual pauses for the commas
also helps reinforce the order of operation (important with - or /
more so than + or *).

-Dave
1d57c32d7712e7222dbbfdc363473837?d=identicon&s=25 Avdi Grimm (Guest)
on 2014-01-03 20:06
(Received via mailing list)
What I've learned after many conversations about #inject and its aliases
is
that there is no one metaphor that works for this particular concept.
For
everyone who thinks "fold" makes perfect sense, there's someone else who
thinks it's nonsense and that "accumulate", "aggregate", "reduce", or
"inject" make way more sense.


On Fri, Jan 3, 2014 at 1:54 PM, Dave Aronson
F141ba99f29e55f02207f5488fe5ce95?d=identicon&s=25 Dave Aronson (Guest)
on 2014-01-03 20:21
(Received via mailing list)
On Fri, Jan 3, 2014 at 2:06 PM, Avdi Grimm <groups@inbox.avdi.org>
wrote:

> What I've learned after many conversations about #inject and its aliases
> is that there is no one metaphor that works for this particular concept.

Agreed.  I didn't grok why other languages called it "fold" until
someone told me the map metaphor.  (Admittedly, Ruby is the only one
I've used a *lot* with such a concept.)  The "inject into the spaces"
metaphor is one I came up with when trying to explain to a Ruby-newbie
what inject did.  (Presumably others came up with it too; that may
even be how the name came about.  Anybody know?)  Reduce made sense
because I had already heard of map-reduce, but even then, as someone
else pointed out, "reduce" doesn't necessarily mean "to one".

If I were coming up with a name for it, for a new language, I think
"accumulate" would be my choice, by reference to the concept of an
accumulator.  Even that, though, would be unclear to someone without a
solid CS/coding background already.

Maybe we should just make up a new word and confuse everybody equally.
 Where'd I put that random D&D character name generator.... ;-)

-Dave
9a45896e48a382fe5c656b8873e0dfcb?d=identicon&s=25 Stu (Guest)
on 2014-01-03 20:36
(Received via mailing list)
@Avdi

=) Yup. It's a great concept. Smalltalk was built on another AI language
which uses cells which in turn branch in form of linked lists with a
atomic
dereference value and a pointer to the next cell in the tree. OO
messaging
is totally based on the concept where objects communicate with signals
and
messages over a network. The concept of a self described system wasn't
exactly a new concept but definitely brought to a new level of control
moving into graphical systems.

@Kal
I didn't refer to it being different. I mentioned that the alias to the
"sameness" of the functions will be applicable to current programmers
which
are writing code. Hence a SQL programmer might like /select/ a UNIX
programmer would use /grep/ a haskall programmer would feel comfortable
with /fold/ where a scheme programmer would use /reduce/. An erlang
programmer would embed their own MapReduce filter  which would have a
slick
side effect providing the removal of the jvm virus inside an ad hoc
parser
on a zero width atomic contexts which would recursively reduce all ruby
code through an EvalApply self.reference reducer modulo whitespace into
a
try-retry cycled core routine emitting a prolog based truth maintenance
system implemented minikanren system built with nothing more than
regular
expressions!

It's a programmable programming language! Know thy computational models
and
metaphors yet keep all aliases and subroutines intact and in core as to
respect all programmers with different backgrounds!
F9bd1f8df35143db8bb314e2732b717c?d=identicon&s=25 Kal Starkis (kal)
on 2014-01-03 20:47
Dave Aronson wrote in post #1132148:
> The "inject into the spaces"
> metaphor is one I came up with when trying to explain to a Ruby-newbie
> what inject did.  (Presumably others came up with it too;

Look no further than this very thread! See Jim Weirich's first comment.

> that may
> even be how the name came about.  Anybody know?)

It seems to take its name from Smalltalk's inject:into: method. I'm not
familiar with Smalltalk, but here's an example of that method taken from
Wikipedia:

#(1 3 5) inject: 10 into: [ :sum :element | sum + element ] "=> 19"

Based on how it reads 'inject 10 into [block]' (10 being the
first value for :sum), the idea seems to be of injecting the new result
back into the block upon each iteration, rather than injecting the block
between elements of the original object.

> Reduce made sense
> because I had already heard of map-reduce…

Yes, but wouldn't map-fold be so much cooler? :-)
F9bd1f8df35143db8bb314e2732b717c?d=identicon&s=25 Kal Starkis (kal)
on 2014-01-03 21:01
Wooosh! (The sound of Stu's comment flying over my head.) I'll have to
take your word for it mate! :-)
9a45896e48a382fe5c656b8873e0dfcb?d=identicon&s=25 Stu (Guest)
on 2014-01-03 21:49
(Received via mailing list)
@Kal maybe this will help:

Here is the concept in done fizzbuzz style list :
The problem: Write a function foo that takes a number n and returns a
function that takes a number i, and returns n incremented by i.

http://www.paulgraham.com/accgen.html

which is an extension to this inglorious rant on managerial driven
development (MDD)
http://www.paulgraham.com/icad.html

~Stu
B238111fbaec95d3f8e8917d3ee32a7e?d=identicon&s=25 Michael Mitchel (variousred)
on 2014-06-12 19:07
Jeff Pritchard wrote in post #80239:
> Can anybody explain to me how the Enumberable#inject method is
> "injecting" something into something?  I find it very difficult remember
> method names when I don't "get" them.  So far in Ruby, "inject" takes
> the cake for least understandable method name (with my own particular
> convoluted gray matter).
>
> Can somebody give some examples of its use and state in words how it is
> "injecting" something into something?
>
> thanks,
> jp
>
> P.S.
> If anybody wants to take a stab at "collect", that would be welcome
> also.

My brain works exactly the same way. In fact thats why i wound up here
reading your question! Thanks for asking it.

Michael
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.