Skip to content

Instantly share code, notes, and snippets.

@floehopper
Forked from chrislo/gist:8543385
Last active January 4, 2016 01:29
Show Gist options
  • Save floehopper/8548547 to your computer and use it in GitHub Desktop.
Save floehopper/8548547 to your computer and use it in GitHub Desktop.
Evaluator for Little Schemer chapter 1
class Atom
attr_reader :symbol
def initialize(symbol)
@symbol = symbol
end
def ==(other)
self.symbol == other.symbol
end
end
class Evaluator
def initialize(program)
@program = program
end
def evaluate(env={})
function, argument = @program.car, @program.cdr.car
operation = function.symbol
case argument
when Atom
env[argument.symbol].send(operation)
when List
self.class.new(argument).evaluate(env).send(operation)
else
raise
end
end
end
require 'minitest/autorun'
require_relative 'atom'
require_relative 'list'
require_relative 'evaluator'
class EvaluatorTest < Minitest::Test
def test_car
assert_equal Atom.new(:a), evaluate(
List.new(Atom.new(:car), Atom.new(:l)),
l: List.new(Atom.new(:a), Atom.new(:b), Atom.new(:c))
)
end
def test_car_car
assert_equal Atom.new(:hotdogs), evaluate(
List.new(Atom.new(:car), List.new(Atom.new(:car), Atom.new(:l))),
l: List.new(List.new(Atom.new(:hotdogs), Atom.new(:and)))
)
end
def test_cdr
assert_equal List.new(Atom.new(:b), Atom.new(:c)), evaluate(
List.new(Atom.new(:cdr), Atom.new(:l)),
l: List.new(Atom.new(:a), Atom.new(:b), Atom.new(:c))
)
end
private
def evaluate(program, env={})
Evaluator.new(program).evaluate(env)
end
end
class List
def initialize(*array)
@array = array
end
def car
@array.first
end
def cdr
self.class.new(*@array[1..-1])
end
def ==(other)
self.array == other.array
end
protected
attr_reader :array
end
@tomstuart
Copy link

Great!

The book hasn’t yet told us how to provide a literal (i.e. unevaluated) list argument to car and cdr, so IMO only the *_with_environment_lookup tests make sense.

@tomstuart
Copy link

I guess what I mean is: the book doesn’t say “(car (a b c)) is a” or “(cdr (a b c)) is (b c)”, but the tests do.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment