Today I slightly refine the nascent OO implementation in Elixir. Here’s the new point constructor, with methods contained within it:
def new_point(x, y) do [ x: x, y: y, __class_symbol__: :point, __methods__: [ class: &get(&1, :__class_symbol__), shift: fn (this, xinc, yinc) -> new_point(get(this, :x) + xinc, get(this, :y) + yinc) end ] ] end
And here’s send_to, which (slightly) eases sending messages to objects.
@doc """ ## Examples iex> p = make(point, [3, 5]) iex> p2 = send_to(p, :shift, [2,4]) iex> Dict.get(p2, :x) 5 iex> Dict.get(p2, :y) 9 """ def send_to(object, message, args // []) do method_table = get(object, :__methods__) method = get(method_table, message) apply(method, [object|args]) end
Exercise 1: x, y, and add
This exercise re-adds x, y, and add methods.
@doc """ iex> p1 = make(point, [3,5]) iex> p2 = make(point, [-2,3]) iex> p3 = send_to(p1, :add, [p2]) iex> send_to(p3, :x) 1 iex> send_to(p3, :y) 8 """ def new_point(x, y) do [ x: x, y: y, __class_symbol__: :point, __methods__: [ class: &get(&1, :__class_symbol__), shift: fn (this, xinc, yinc) -> new_point(get(this, :x) + xinc, get(this, :y) + yinc) end, x: &get(&1, :x), y: &get(&1, :y), add: fn (this, other) -> send_to(this, :shift, [send_to(other, :x), send_to(other, :y)]) end ] ] end
This is all quite horrible so far; presumably I’ll be cleaning it up as I progress further in the book.