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.
on 2006-05-21 04:42
on 2006-05-21 04:54
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]
on 2006-05-21 04:58
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
on 2006-05-21 05:08
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
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?
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
on 2006-05-21 07:28
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.
on 2006-05-21 07:34
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.
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.
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..
on 2006-05-21 09:29
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.
on 2006-05-21 09:33
[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
on 2006-05-21 11:49
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
on 2006-05-21 13:17
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
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.
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.
on 2006-05-21 17:22
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.
on 2006-05-21 18:02
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
on 2006-05-21 18:08
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
on 2006-05-21 18:45
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.
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
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
on 2006-05-22 11:28
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!
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.
on 2006-05-22 12:16
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.
on 2006-05-22 12:17
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
on 2006-05-22 13:36
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}"
on 2006-05-22 13:42
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
on 2006-05-22 13:42
> ..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}
on 2006-05-22 13:54
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!)
on 2006-05-22 13:58
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
on 2006-05-22 15:48
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
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
on 2006-05-22 16:59
> 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 2006-05-24 18:24
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
on 2006-05-24 21:48
"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.)
on 2006-05-24 22:08
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
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
on 2006-05-24 23:44
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
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
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.
on 2007-03-01 12:32
> 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
on 2007-03-01 12:34
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
on 2007-03-01 17:43
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
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.