"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!"