Reputation: 1041
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 the if/else clause?
Upvotes: 3
Views: 1169
Reputation: 48649
The *
either collects all the items into an array, or explodes an array into individual elements--depending on the context.
If args = [1, 2, 3]
, then:
f[args]
is equivalent to f[ [1, 2, 3] ] #There is one argument: an array.
f[*args]
is equivalent to f[1, 2, 3] #There are three arguments.
If f[*args]
returns [4, 5, 6]
, then:
self[f[*args]]
is equivalent to self[ [4, 5, 6] ] #self is called with 1 arg.
self[*f[*args]]
is equivalent to self[4, 5, 6] #self is called with 3 args.
An example of *
being used to collect items into an Array is:
lambda {|*args| ....}
You can call that function with any number of arguments, and all the arguments will be collected into an array and assigned to the parameter variable args
.
Upvotes: 5
Reputation: 84182
*
(also known as splat) allows you to call a method with an array of arguments rather than passing the values individually. If you left off the splat then ruby would just pass a single value (that happens to be an array). This unary *
is not the *
operation that this code defines as an alias of compose
In the if branch self
has an arity of 1, then f
should be returning a single value and so there is no need for the splat.
In the else branch self
takes more than one argument, it follows that f
should return an array of values, and the splat is used to call self
with those arguments.
Upvotes: 0