[boilerplate bypath=”fp-oo”]

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.

Published by Avdi Grimm

Leave a Reply

Your email address will not be published. Required fields are marked *