How does the compose (*) function work in Ruby (from the Ruby programming language)?
Excerpt The Ruby Programming Language:
module Functional
def compose(f)
if self.respond_to?(:arity) && self.arity == 1
lambda {|*args| self[f[*args]] }
else
lambda {|*args| self[*f[*args]] }
end
end
alias * compose
end
class Proc; include Functional; end
class Method; include Functional; end
f = lambda {|x| x * 2 }
g = lambda {|x, y| x * y}
(f*g)[2, 3] # => 12
What is the difference between f and * f in an if / else clause?
source to share
*
either collects all the elements into an array, or explodes the array into individual elements - depending on the context.
If args = [1, 2, 3]
, then:
-
f[args]
equivalentf[ [1, 2, 3] ] #There is one argument: an array.
-
f[*args]
equivalentf[1, 2, 3] #There are three arguments.
If it f[*args]
returns [4, 5, 6]
, then:
-
self[f[*args]]
equivalentself[ [4, 5, 6] ] #self is called with 1 arg.
-
self[*f[*args]]
equivalentself[4, 5, 6] #self is called with 3 args.
An example *
used to collect items in an array is:
-
lambda {|*args| ....}
You can call this function with any number of arguments, and all arguments will be collected into an array and assigned to the parameter variable args
.
source to share
*
(also known as splat) allows you to call a method with an array of arguments rather than passing values individually. If you settled on splat then ruby will just pass one value (it will be an array). This unary is *
not an operation *
that this code defines as an aliascompose
The if branch self
has an arty of 1, then f
should return a single value and therefore no need for splat.
The else branch self
accepts multiple arguments, which means it f
should return an array of values, and splat is used to call self
with those arguments.
source to share