I think I just need to keep a list of a fixed length in process’s memory. So that when the new data comes in, that last element gets removed from the list and the new data gets put in the head of the list.
old_list = [b, c, d]
# new data `a` comes in
new_list = update(old_list, a)
new_list == [a, b, c]
Don’t know how to do that without pointers … Will look into how :queue
module works.
defmodule Quote.History do
@type t :: {new :: list, old :: list}
def new do
{[], []}
end
@doc """
iex> new([3, 2, 1])
{[3], [1, 2]}
"""
@spec new(list) :: t
def new(list)
def new([h | t]) do
{[h], :lists.reverse(t)}
end
@doc """
iex> history = new([3, 2, 1])
iex> history |> push(4) |> to_list()
[4, 3, 2]
"""
@spec to_list(t) :: list
def to_list({new, old}) do
new ++ :list.reverse(old)
end
@doc """
iex> history = {[3], [1, 2]} = new([3, 2, 1])
iex> push(history, 4)
{[4, 3], [2]}
iex> push({[4, 3], [2]}, 5)
{[5, 4, 3], []}
iex> push({[5, 4, 3], []}, 6)
{[6, 5], [4]}
"""
@spec push(t, any) :: t
def push(hisroty, element)
def push({new, [_ | rest]}, element) do
{[element | new], rest}
end
def push({[new | rest], []}, element) do
[_ | old] = :lists.reverse(rest)
{[element, new], old}
end
def push({[], []}, element) do
{[], [element]}
end
end
Something like this maybe. Don’t like all these calls to :lists.reverse
…
Seems to work. But also seems hacky …
Interactive Elixir (1.6.0) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> history = Quote.History.new [3, 2, 1]
{[3], [1, 2]}
iex(2)> Quote.History.to_list history
[3, 2, 1]
iex(3)> Quote.History.push history, 4
{[4, 3], [2]}
iex(4)> history = Quote.History.push history, 4
{[4, 3], [2]}
iex(5)> Quote.History.to_list history
[4, 3, 2]
iex(6)> history = Quote.History.push history, 5
{[5, 4, 3], []}
iex(7)> Quote.History.to_list history
[5, 4, 3]
iex(8)> history = Quote.History.push history, 6
{[6, 5], [4]}
iex(9)> Quote.History.to_list history
[6, 5, 4]