Module: Fear::PartialFunction

Included in:
Combined
Defined in:
lib/fear/partial_function.rb,
lib/fear/partial_function/any.rb,
lib/fear/partial_function/empty.rb,
lib/fear/partial_function/guard.rb,
lib/fear/partial_function/lifted.rb,
lib/fear/partial_function/or_else.rb,
lib/fear/partial_function/and_then.rb,
lib/fear/partial_function/combined.rb,
lib/fear/partial_function/guard/or.rb,
lib/fear/partial_function/guard/and.rb,
lib/fear/partial_function/guard/and3.rb

Overview

A partial function is a unary function defined on subset of all possible inputs. The method defined_at? allows to test dynamically if an arg is in the domain of the function.

Even if defined_at? returns true for given arg, calling call may still throw an exception, so the following code is legal:

@example
  Fear.case(->(_) { true }) { 1/0 }

It is the responsibility of the caller to call defined_at? before calling call, because if defined_at? is false, it is not guaranteed call will throw an exception to indicate an error guard. If an exception is not thrown, evaluation may result in an arbitrary arg.

The main distinction between PartialFunction and Proc is that the user of a PartialFunction may choose to do something different with input that is declared to be outside its domain. For example:

The method or_else allows chaining another partial function to handle input outside the declared domain

numbers = sample.map(is_even.or_else(is_odd).to_proc)

Examples:

sample = 1...10

is_even = Fear.case(->(arg) { arg % 2 == 0}) do |arg|
  "#{arg} is even"
end

is_odd = Fear.case(->(arg) { arg % 2 == 1}) do |arg|
  "#{arg} is odd"
end

See Also:

Defined Under Namespace

Classes: Any, Combined, Guard

Constant Summary collapse

EMPTY =
Object.new.extend(EmptyPartialFunction)

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.and(*guards, &function) ⇒ Fear::PartialFunction

Creates partial function guarded by several condition. All guards should match.

Parameters:

  • guards (<#===, symbol>)
  • function (Proc)

Returns:



157
158
159
# File 'lib/fear/partial_function.rb', line 157

def and(*guards, &function)
  PartialFunctionClass.new(Guard.and(guards), &function)
end

.or(*guards, &function) ⇒ Fear::PartialFunction

Creates partial function guarded by several condition. Any condition should match.

Parameters:

  • guards (<#===, symbol>)
  • function (Proc)

Returns:



166
167
168
# File 'lib/fear/partial_function.rb', line 166

def or(*guards, &function)
  PartialFunctionClass.new(Guard.or(guards), &function)
end

Instance Method Details

#&(other) ⇒ Object

See Also:



141
142
143
# File 'lib/fear/partial_function.rb', line 141

def &(other)
  and_then(other)
end

#and_then(other) ⇒ Fear::PartialFunction #and_then(other) ⇒ Fear::PartialFunction #and_then(&other) ⇒ Fear::PartialFunction

Composes this partial function with a fallback partial function (or Proc) which gets applied where this partial function is not defined.

Overloads:

  • #and_then(other) ⇒ Fear::PartialFunction
    Note:

    calling #defined_at? on the resulting partial function may call the first partial function and execute its side effect. It is highly recommended to call #call_or_else instead of #defined_at?/#call for efficiency.

    Returns a partial function with the same domain as this partial function, which maps argument x to other.(self.call(x)).

    Parameters:

    Returns:

    • (Fear::PartialFunction)

      a partial function with the same domain as this partial function, which maps argument x to other.(self.call(x)).

  • #and_then(other) ⇒ Fear::PartialFunction

    Returns a partial function with the same domain as this partial function, which maps argument x to other.(self.call(x)).

    Parameters:

    • other (Proc)

    Returns:

    • (Fear::PartialFunction)

      a partial function with the same domain as this partial function, which maps argument x to other.(self.call(x)).

  • #and_then(&other) ⇒ Fear::PartialFunction

    Parameters:

    • other (Proc)

    Returns:



130
131
132
133
134
135
136
137
138
# File 'lib/fear/partial_function.rb', line 130

def and_then(other = Utils::UNDEFINED, &block)
  Utils.with_block_or_argument('Fear::PartialFunction#and_then', other, block) do |fun|
    if fun.is_a?(Fear::PartialFunction)
      Combined.new(self, fun)
    else
      AndThen.new(self, &fun)
    end
  end
end

#call(arg) ⇒ any

This method is abstract.

Returns Calls this partial function with the given argument when it is contained in the function domain.

Parameters:

  • arg (any)

Returns:

  • (any)

    Calls this partial function with the given argument when it is contained in the function domain.

Raises:

  • (MatchError)

    when this partial function is not defined.



# File 'lib/fear/partial_function.rb', line 65

#call_or_else(arg) {|arg| ... } ⇒ Object

Note:

that expression pf.call_or_else(arg, &fallback) is equivalent to pf.defined_at?(arg) ? pf.(arg) : fallback.(arg) except that call_or_else method can be implemented more efficiently to avoid calling defined_at? twice.

Calls this partial function with the given argument when it is contained in the function domain. Calls fallback function where this partial function is not defined.

Parameters:

  • arg (any)

Yields:

  • (arg)

    if partial function not defined for this arg



89
90
91
92
93
94
95
# File 'lib/fear/partial_function.rb', line 89

def call_or_else(arg)
  if defined_at?(arg)
    call(arg)
  else
    yield arg
  end
end

#defined_at?(arg) ⇒ Boolean

Checks if a value is contained in the function’s domain.

Parameters:

  • arg (any)

Returns:

  • (Boolean)


61
62
63
# File 'lib/fear/partial_function.rb', line 61

def defined_at?(arg)
  condition === arg
end

#initialize(condition, &function) ⇒ Object

Parameters:

  • condition (#call)

    describes the domain of partial function

  • function (Proc)

    function definition



49
50
51
52
# File 'lib/fear/partial_function.rb', line 49

def initialize(condition, &function)
  @condition = condition
  @function = function
end

#lift#call

Turns this partial function in Proc-like object, returning Option

Returns:



147
148
149
# File 'lib/fear/partial_function.rb', line 147

def lift
  Lifted.new(self)
end

#or_else(other) ⇒ PartialFunction

Composes this partial function with a fallback partial function which gets applied where this partial function is not defined.

Parameters:

Returns:

  • (PartialFunction)

    a partial function which has as domain the union of the domains of this partial function and other.



103
104
105
# File 'lib/fear/partial_function.rb', line 103

def or_else(other)
  OrElse.new(self, other)
end

#to_procProc

Converts this partial function to other

Returns:

  • (Proc)


75
76
77
# File 'lib/fear/partial_function.rb', line 75

def to_proc
  proc { |arg| call(arg) }
end

#|(other) ⇒ Object

See Also:



108
109
110
# File 'lib/fear/partial_function.rb', line 108

def |(other)
  or_else(other)
end