From: Trans Date: 2007-11-12T09:45:13+09:00 Subject: Re: equivalent injecting implementations? On Nov 11, 6:15 pm, "Rick DeNatale" wrote: > On Nov 11, 2007 1:39 PM, Trans wrote: > > > > > > > On Nov 11, 9:50 am, "Rick DeNatale" wrote: > > > Yes, I suspected that this was what Trans was trying to do, but since > > > the second proposed 'maybe equivalent' implementation didn't seem to > > > be doing the same thing, I was probing for what he really wanted. > > > > Having said that, and played a bit with the concept. I'm not sure how > > > useful an injecting method (at least with that name is). > > > > As Robert Klemme points out, it breaks depending on what you are > > > injecting. And it's subject to "cargo culting." > > > > module Enumerable > > > def injecting(obj, &blk) > > > inject(obj) { |mem, var| yield(mem, var); mem } > > > end > > > end > > > > As Ezra points out: > > > > [1,2,3].inject({}) { |memo,n| memo[n] = n ; memo} # => {1=>1, 2=>2, 3=>3} > > > [1,2,3].injecting({}) { |memo,n| memo[n] = n} # => {1=>1, 2=>2, 3=>3} > > > > But this only works because the block has a side-effect on the memo > > > object. And yes, in cases like this each instead of inject will have > > > the same side effects. > > > > [1,2,3].inject(0) { |memo,n| memo + n} # => 6 > > > [1,2,3].injecting(0) { |memo,n| memo + n} # => 0 > > > > Here's where the cargo cult danger comes in. Someone who comes across > > > 'injecting' without understanding it might run into things like this. > > > Hmmm... does this mean that the same effect can be achieved with: > > > module Enumerable > > def inject!(obj) > > each { |var| yield(obj, var) } > > obj > > end > > end > > If you mean the same effect as the current inject. NO. This fails for > the case I cited: No. That's not what I meant. I realize the difference between inject and injecting. I'm interested in the implementations of injecting. > The redefinition would change the results the last example to return 0 > instead of 5. And it would make the other ones illegal since it > requires the initial parameter. You misunderstand me. I have no intention of that. inject and injecting are different. > Now I noticed that you picked up David Black's suggestion of inject! > instead of inject, but I took the :-) that he added as an indication > that it was tongue in cheek. Joke or not it seems appropriate.'!' often in indicates in place action. > If I may be so bold as to suggest that injecting as posited by Ezra > might really be a result of cargo culting the "k combinator" > represented by Object#returning with a slightly less than perfect > understanding of Enumerable#inject. > > His motivating example: > > [1,2,3].inject({}) { |memo,n| memo[n] = n ; memo} # => {1=>1, 2=>2, 3=>3} > > Is an unusual use of inject. It might just as well be written as: > > h = {}; [1, 2, 3].each {|i| h[i] = i}; h > > Which admittedly is uglier due to the need to use the temporary h, and > rename it. But here's an alternative way to accomplish Ezra's use case > using Object#returning (which is implemented as part of the > ActiveSupport gem): > > # This is the definition of Object#returning from ActiveSupport > class Object > def returning(value) > yield(value) > value > end > end > > # Ezra's example of injecting was: > # [1,2,3].injecting({}) { |memo,n| memo[n] = n } # => {1=>1, 2=>2, 3=>3} > > # The same thing using returning > returning({}) {|hsh| [1,2,3].each {|i| hsh[i] = i}} # => {1=>1, 2=>2, 3=>3} I see the formal equivalence. But if I ever used that, please take my keyboard away. T.