module Cuprum::Currying

Implements partial application for command objects.

Partial application (more commonly referred to, if imprecisely, as currying) refers to fixing some number of arguments to a function, resulting in a function with a smaller number of arguments.

In Cuprum's case, a curried (partially applied) command takes an original command and pre-defines some of its arguments. When the curried command is called, the predefined arguments and/or keywords will be combined with the arguments passed to call.

@example Currying Arguments

# Our base command takes two arguments.
say_command = Cuprum::Command.new do |greeting, person|
  "#{greeting}, #{person}!"
end
say_command.call('Hello', 'world')
#=> returns a result with value 'Hello, world!'

# Next, we create a curried command. This sets the first argument to
# always be 'Greetings', so our curried command only takes one argument,
# namely the name of the person being greeted.
greet_command = say_command.curry('Greetings')
greet_command.call('programs')
#=> returns a result with value 'Greetings, programs!'

# Here, we are creating a curried command that passes both arguments.
# Therefore, our curried command does not take any arguments.
recruit_command = say_command.curry('Greetings', 'starfighter')
recruit_command.call
#=> returns a result with value 'Greetings, starfighter!'

@example Currying Keywords

# Our base command takes two keywords: a math operation and an array of
# integers.
math_command = Cuprum::Command.new do |operands:, operation:|
  operations.reduce(&operation)
end
math_command.call(operands: [2, 2], operation: :+)
#=> returns a result with value 4

# Our curried command still takes two keywords, but now the operation
# keyword is optional. It now defaults to :*, for multiplication.
multiply_command = math_command.curry(operation: :*)
multiply_command.call(operands: [3, 3])
#=> returns a result with value 9

Public Instance Methods

curry(*arguments, **keywords, &block) click to toggle source

Returns a CurriedCommand that wraps this command with pre-set arguments.

When the curried command is called, the predefined arguments and/or keywords will be combined with the arguments passed to call.

The original command is unchanged.

@param arguments [Array] The arguments to pass to the curried command. @param keywords [Hash] The keywords to pass to the curried command.

@return [Cuprum::Currying::CurriedCommand] the curried command.

@see Cuprum::Currying::CurriedCommand#call

# File lib/cuprum/currying.rb, line 68
def curry(*arguments, **keywords, &block)
  return self if arguments.empty? && keywords.empty? && block.nil?

  Cuprum::Currying::CurriedCommand.new(
    arguments: arguments,
    block:     block,
    command:   self,
    keywords:  keywords
  )
end