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.