Class: Campa::Lambda

Inherits:
Object
  • Object
show all
Defined in:
lib/campa/lambda.rb

Overview

Represents an anonymous function that will be executed in a given Context.

Examples:

# given the representation of
# ((lambda (something) (print something)) "hello world")
lbd = Lambda.new(
  [Symbol.new("something")],
  [List.new(Symbol.new("print"), Symbol.new("something"))]
)

# sends "hello world" to the $stdout and returns
lbd.call("hello world") #=> nil

working with closures:


# given the representation of
# (label meaning 42)
# ((lambda (time) (print "time: " time " meaning of life: " meaning)) 420)
ctx = Context.new(Symbol.new("meaning") => 42)

lbd = Lambda.new(
  [Symbol.new("time")],
  [
    List.new(
      Symbol.new("print"),
      "time: ", Symbol.new("time"),
      ", meaning of life: ", Symbol.new("meaning")
    )
  ],
  ctx
)

# sends "time: 420, meaning of life: 42" to $stdout and returns
lbd.call(420) #=> nil

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(params, body, closure = Context.new) ⇒ Lambda

Returns a new instance of Lambda.

Parameters:

  • params (Array<Symbol>)

    Symbols naming the parameters that a lambda can receive when being invoked

  • body (Array<Object>)

    expressions composing the body, they are executed one by one in order in the given Context

  • closure (Context) (defaults to: Context.new)

    used as a fallback for the Context given when the Campa::Lambda is executed



47
48
49
50
51
52
# File 'lib/campa/lambda.rb', line 47

def initialize(params, body, closure = Context.new)
  @params = params
  @body = Array(body)
  @closure = closure
  @evaler = Evaler.new
end

Instance Attribute Details

#bodyObject (readonly)

Returns the value of attribute body.



38
39
40
# File 'lib/campa/lambda.rb', line 38

def body
  @body
end

#closureObject (readonly)

Returns the value of attribute closure.



38
39
40
# File 'lib/campa/lambda.rb', line 38

def closure
  @closure
end

#paramsObject (readonly)

Returns the value of attribute params.



38
39
40
# File 'lib/campa/lambda.rb', line 38

def params
  @params
end

Instance Method Details

#==(other) ⇒ Boolean

Stablishes equality between Campa::Lambda objects by comparing #params and #body

Parameters:

Returns:



86
87
88
89
90
# File 'lib/campa/lambda.rb', line 86

def ==(other)
  return false if !other.is_a?(Campa::Lambda)

  params == other.params && body == other.body
end

#call(*args, env:) ⇒ Object

Executes the expressions contained in the #body one by one using as Context the parameter env: on this method.

The env: param will be used here as a fallback to a brand new Context created in the moment of the invocation. This isolates the Context passed as a parameter of any mutations that would be created by the Campa::Lambda if there is any binding during the execution.

Parameters:

  • args (Array<Object>)

    the values that will be bound to each of the #params given to the constructor

  • env (Context)

    for the execution of a lambda

Returns:

  • (Object)

    result of evaluating the last expression on #body



69
70
71
72
73
74
75
76
77
78
# File 'lib/campa/lambda.rb', line 69

def call(*args, env:)
  raise arity_error(args) if params.to_a.length != args.length

  @body.reduce(nil) do |_, expression|
    evaler.call(
      expression,
      invocation_env(env, args)
    )
  end
end