Class: Lambda

Inherits:
BasicObject
Defined in:
lib/patch/lambda.rb

Overview

A Lambda object (‘_`) is building block for anonymous functions. For instance, (`_ + _`) represents f(x,y) = x + y (`_ * 2`) represents f(x) = 2x. You can use any method or operator on a `_`, and it will work:

  • ‘[1, 2].map(&_.succ ** 3) => [8, 27]`

  • ‘[[1,2], [3,4]].map(&_.sum / 2) => [1.5, 3.5]`

The ‘lift` method allows a `_` to be used like so:

  • ‘[[1, 2], [3, 4]].map(&(_ + _).lift) => [3, 7]`

i.e. it treats the first arg (that is an array) as the actual arguments to be used WARN: “lift” state is contagious (e.g. ‘(_ + _.lift) <=> (_ + _).lift`).

You can similarly use [unlift] to convert a lifted ‘_` back to a normal.

support_lambda

will allow for a _ to be used as the second operand (e.g. ‘2 - _`)

Defined Under Namespace

Classes: Arg, Block, Function, Repr

Instance Method Summary collapse

Constructor Details

#initialize(repr = [Arg.new], *args) ⇒ Lambda

Returns a new instance of Lambda.



64
65
66
67
68
69
70
71
72
# File 'lib/patch/lambda.rb', line 64

def initialize(repr = [Arg.new], *args)
  @__tuply__ = args.include?(:lift)
  @__repr__ = repr

  return if repr != :lift

  @__repr__ = [Arg.new]
  @__tuply__ = true
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/patch/lambda.rb', line 116

def method_missing(method, *args, &block)
  extra = [Function.new(method)]
  extra.unshift Block.new(block) if block
  tuply = @__tuply__

  args.map do |arg|
    if arg.is_a?(::Lambda)
      tuply ||= arg.__tuply__
      Repr.new(arg.__repr__)
    else
      arg
    end
  end.each_with_index do |arg, i|
    if arg.is_a? Repr
      args.insert(i, *arg.repr)
      args.delete_at(i + arg.repr.size)
    end
  end

  if tuply
    ::Lambda.new(@__repr__ + args + extra, :lift)
  else
    ::Lambda.new(@__repr__ + args + extra)
  end
end

Instance Method Details

#__repr__Object



61
# File 'lib/patch/lambda.rb', line 61

def __repr__; @__repr__ end

#__tuply__Object



62
# File 'lib/patch/lambda.rb', line 62

def __tuply__; @__tuply__ end

#liftObject



142
143
144
# File 'lib/patch/lambda.rb', line 142

def lift
  ::Lambda.new(@__repr__, :lift)
end

#to_procObject



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/patch/lambda.rb', line 74

def to_proc
  ::Proc.new do |*args|
    args = args.first if @__tuply__ && args.first.is_a?(::Array)
    stack = []
    index = 0

    @__repr__.each do |element|
      case element
      when Arg
        stack << args[index]
        index += 1
      when Function
        f = element.to_proc
        operands, block = stack.partition { |e| !e.is_a?(Block) }
        empty = ::Object.new
        xy = [operands.qoq(empty), operands.qoq(empty)]
          .reject { |x| x.equal?(empty) }.reverse
        stack = operands

        if block.empty?
          stack << f.call(*xy)
        else
          stack << f.call(*xy, &block[0].to_proc)
        end
      else
        stack << element
      end
    end

    stack.first
  end
end

#unliftObject



146
147
148
# File 'lib/patch/lambda.rb', line 146

def unlift
  @__tuply__ ? ::Lambda.new(@__repr__) : self
end