"georgesawyer" <georgesawyer2 / hotmail.ok.nospam.com> Jan 28, 2005 at 12:58 PM in thread "Re: Convert a Hash into an Array" wrote: >georgesawyer wrote: >>"Robert Klemme" <bob.news / gmx.net> Jan 25, 2005 at 09:09 AM wrote: >>>did I mention that I love #inject? :-) >>(Wistfully) Even though 'inject' is the name in Smalltalk, I feel it were better named, 'consolidate'. >More fundamentally, I suggest 'collapse', because the most general concept seems [to be] of collapsing-away one dimension from a multi-dimensional thing. ... Pushing the concept to all dimensions would be done ... first by [slightly] flatten'ing, then by inject'ing (collapse'ing). Reducing the dimensionality by one seems useful: here and there, I seem to have heard of this. >I lack some comfort with 'inject', even after time: perhaps because it asks us to pass the code for collapsing (an array of) objects, instead of asking the objects to know how to collapse themselves: a known object-programming principle. Collapse perhaps should be a module method of no arguments, mix-inable to any class of objects having the '[]' method. Following is sample code for what I think is the essence of it: Mark Blackwell =begin License: GPL (GNU General Public License) Name: module Cascade Author: Mark Blackwell Writing started: 1/28/2005 Written through: 2/3/2005 To replace current method "inject" (not the general idea of injection: e.g., dependency injection). Cascade is richer in addition to doing sums, products, etc. Affects two classes: Class one, typically derived from Array, mixes in module Cascade. Two, not necessarily a class, is any objects with methods "cascade_zero" and "cascade_operation". The cascade method typically runs through an array: any object with methods "first" and "each". The object yielded by this "first" method (e.g., an array's first element) must have a method "cascade_zero". Every object yielded by this "each" method (e.g., an array's elements) must have a method "cascade_operation". Naturally, the cascade_operation's can vary among the objects. This provides, for one thing, for cascading our work. Long procedures, or depths of application layers, both requiring temporary variables, seem more difficult to read. Judiciously, they might be refactored, instead invoking method "cascade" once, and thus coordinating the action hierarchy in one place. =end module Cascade def cascade register =( self.first.method :cascade_zero).call self.each {|e| register =( e.method :cascade_operation).call( register ,e)} register end end # module Cascade module Testing class A < Array ;include Cascade end # ------------------------- class O ;def to_i ;@v end end # Objects with unique operations: class O1 < O ;def cascade_zero ;@z end def initialize( z ,v) ;@z =z ;@v =v end def cascade_operation( c ,d) ; c +d.to_i end end class O2 < O ;def initialize( v) ;@v =v end def cascade_operation( c ,d) ; c *d.to_i end end class O3 < O ;def initialize( v) ;@v =v end def cascade_operation( c ,d) ; c -d.to_i end end # ------------------------- class ForMultiDimensionalArray def initialize( v) ;@v =v end def []( i) ;@v.at i end def cascade_zero ;[ 1 ,1] end # Very primitive, but gives the idea: def cascade_operation( c ,d) ;[ c[0] *d[0] ,c[1] *d[1]] end end # ------------------------- class ActionObjectChain include Cascade class Zero ;def cascade_zero ;"Hello there, " end end class ActionObject attr :s def initialize( s) ;@s =s end def cascade_operation( s ,e) ;s +e.s end end def initialize( v) ;@v =v end def first ;Zero.new end def each ;@v.each {|s| yield ActionObject.new( s)} ;nil end end # ------------------------- # An example "array" of objects with unique operations. first =O1.new( 10 ,20) ;second =O2.new( 50) ;third =O3.new( 70) a =A[ first ,second ,third] p a.cascade # ------------------------- # An example of collapsing a multi-dimensional array. first =ForMultiDimensionalArray.new [ 2 ,3 ] second =ForMultiDimensionalArray.new [ 5 ,7 ] third =ForMultiDimensionalArray.new [ 11 ,13] b =A[ first ,second ,third] p b.cascade # ------------------------- # An example "chain" of action-objects. c =ActionObjectChain.new([ "John " ,"and " ,"Mary" ,"!"]) p c.cascade # ------------------------- # ADD CODE: to give an example that processes multiple GUI windows and events. # ------------------------- end # module Testing __END__ # Results: 1430 [110, 273] "Hello there, John and Mary!"