Class: Proc

Inherits:
Object show all
Defined in:
lib/mug/apply.rb,
lib/mug/functional.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.const(c) ⇒ Object

Generates a constant function that always returns c.

Note that it always returns the same object, so mutations will stick from invocation to invocation.



149
150
151
# File 'lib/mug/functional.rb', line 149

def const c
  lambda {|*| c }
end

.identityObject

Generates an identity function that always returns its argument exactly.



139
140
141
# File 'lib/mug/functional.rb', line 139

def identity
  lambda {|x| x }
end

.juxt(*funcs) ⇒ Object

Generates a function that maps its arguments to the given funcs list in order.



130
131
132
133
134
# File 'lib/mug/functional.rb', line 130

def juxt *funcs
  lambda do |*args|
    funcs.map {|f| f.to_proc.call(*args) }
  end
end

Instance Method Details

#apply(*args) ⇒ Object

Curries this Proc and partially applies parameters. If a sufficient number of arguments are supplied, it passes the supplied arguments to the original proc and returns the result. Otherwise, returns another curried proc that takes the rest of arguments.



13
14
15
16
17
18
19
20
21
22
# File 'lib/mug/apply.rb', line 13

def apply(*args)
  n = arity < 0 ? -arity - 1 : arity
  if lambda?
    curry(n).call(*args)
  elsif args.length >= n
    call(*args)
  else
    proc {|*more| call(*args, *more) }
  end
end

#compose(*funcs) ⇒ Object

Composes a sequence of functions.

A function is anything that responds to #to_proc, so symbols are allowed.

This proc is prepended at the start of the composition.



12
13
14
15
# File 'lib/mug/functional.rb', line 12

def compose *funcs
  return self if funcs.empty?
  self >> funcs.map(&:to_proc).reduce(:>>)
end

#mapply(*args) ⇒ Object

Applies this function to each element of args in order.

‘proc.mapply(*args)` is equivalent to `args.map(&proc)`



35
36
37
# File 'lib/mug/functional.rb', line 35

def mapply *args
  args.map {|*a| self.call(*a) }
end

#memoizeObject Also known as: memoise

Generates a function that memoizes this one. For a given set of parameters, this proc is only invoked once; the result is remembered for subsequent invocations.



44
45
46
47
48
49
# File 'lib/mug/functional.rb', line 44

def memoize
  cache = {}
  lambda do |*args|
    cache.fetch(args) {|_| cache[args] = self.call(*args) }
  end
end

#precompose(*funcs) ⇒ Object

Composes a sequence of functions.

A function is anything that responds to #to_proc, so symbols are allowed.

This proc is appended at the end of the composition.



25
26
27
28
# File 'lib/mug/functional.rb', line 25

def precompose *funcs
  return self if funcs.empty?
  self << funcs.map(&:to_proc).reduce(:>>)
end

#trans(*indices, arity: :min) ⇒ Object

Generates a function that reorders its arguments according to indices and calls this function on the resulting list.

The arity parameter controls how mismatches in length between the arguments and indices are handled:

:min       - cap at the minimum of args and indices (default)
:max       - use the maximum; nil-fill if args are short,
             pass-through if args are long
:indices   - always use indices.size; nil for out-of-bounds
:arguments - always use args.size; excess positions pass
             through at their original index


66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/mug/functional.rb', line 66

def trans *indices, arity: :min
  case arity
  when :min
    lambda do |*a|
      n = [a.size, indices.size].min
      list = (0...n).map {|i| a[indices[i]] }
      self.call(*list)
    end
  when :indices
    lambda do |*a|
      list = (0...indices.size).map {|i| a[indices[i]] }
      self.call(*list)
    end
  when :arguments
    lambda do |*a|
      list = (0...a.size).map do |i|
        i < indices.size ? a[indices[i]] : a[i]
      end
      self.call(*list)
    end
  when :max
    lambda do |*a|
      n = [a.size, indices.size].max
      list = (0...n).map do |i|
        i < indices.size ? a[indices[i]] : a[i]
      end
      self.call(*list)
    end
  else
    raise ArgumentError, "unknown arity mode: #{arity.inspect}"
  end
end

#zipmap(*funcs) ⇒ Object

Generates a function that maps its arguments to each of funcs in order.



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/mug/functional.rb', line 103

def zipmap *funcs
  lambda do |*args|
    n = [args.size, funcs.size].min
    mapped = (0...n).map do |i|
      func = funcs[i]
      arg  = args[i]

      if func.nil?
        arg
      elsif func.respond_to? :call
        func.call arg
      elsif func.is_a? Symbol
        arg.__send__ func
      else
        raise TypeError, "expected callable, Symbol, or nil; got #{func.class}"
      end
    end
    self.call(*mapped)
  end
end