From: Christoph Rippel Date: 2001-02-20T13:50:11+09:00 Subject: [ruby-talk:11152] Re: RCR's > From: Mathieu Bouchard [mailto:matju@cam.org] > On Wed, 14 Feb 2001, Robert Feldt wrote: > > class Proc > > def *(other) > > raise unless arity == other.arity > > proc {|*a| self.call(other.call(*a))} > > end > > end > > wouldn't that be "raise unless arity == 1" ? Actually you are both wrong (the prototypical left/right confusion I never get straight;-) - the ``argument arity'' and the ``arity of the return type'' need to match but the ladder is always -1 that is one element. Morally this is false because this one element (object) is often an array or more generally an object of a collection class and it is tempting to use argument separation to compose more general functions. The basic example is class Proc def *(other) lambda { |a| l, *r = other.call(a); self.call(l,*r)} end end The trouble is that the ``return signature'' is not an invariant for Ruby function and it is not worth the trouble to implement composition with general argument separation IMO. I like (the restricted form) of Roberts function composition proposal but it needs to be supported in the core language IMO - here is a partial solution (note the arity semantics recently changed if I remember correctly). class Proc def *(other) raise 'whatever' unless arity == -1 case other.arity when 0 lambda {|| self.call(other.call) } when -1 lambda {|a| self.call(other.call(a)) } when 2 lambda {|a,b| self.call(other.call(a,b)) } when -2 lambda {|a,*b| self.call(other.call(a,*b)) } else raise 'not implemented' end end end # varying return signature # note the ``return arity'' is always -1 def aa(n) return n if n < 5 return 4,n end a = lambda { |x| aa(x) } b = lambda { |x| x[0]+ x[1] } p a.arity p b.arity c = b * a p c.arity p c.call(5) # => 9 p c.call(4) # => 0 - don't know why # should raise an exception [...] I also wanted to point out that the other functional programming idea - i.e. ``suspend'' - cannot be implemented with Progs IMO. Christoph