Skip to content

Commit

Permalink
Refine Enumerable interface for Array
Browse files Browse the repository at this point in the history
  • Loading branch information
point committed Apr 10, 2024
1 parent 824de3f commit 59d914b
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 4 deletions.
46 changes: 44 additions & 2 deletions lib/y/type/array.ex
Original file line number Diff line number Diff line change
Expand Up @@ -253,10 +253,52 @@ defmodule Y.Type.Array do
{:error, __MODULE__}
end

# def reduce0(%Array{tree: tree} = array, {:cont, acc}, fun) do
# reduce_item = fn
# _, {:halt, acc}, _, _ ->
# {:halted, acc}
#
# [], {:cont, acc}, _fun, _ ->
# {:cont, acc}
#
# [c | rest], {:cont, acc}, fun, reduce_item ->
# reduce_item.(rest, fun.(c, acc), fun, reduce_item)
# end
#
# case ArrayTree.first(tree) do
# nil ->
# {:done, acc}
#
# %{deleted?: true} ->
# reduce(%{array | tree: ArrayTree.rest(tree)}, {:cont, acc}, fun)
#
# %{content: content} ->
# reduce(
# %{array | tree: ArrayTree.rest(tree)},
# reduce_item.(content, {:cont, acc}, fun, reduce_item),
# fun
# )
# end
# end

def reduce(array, acc, fun)

def reduce(%Array{tree: tree}, {:cont, acc}, fun) do
Enumerable.reduce(tree, {:cont, acc}, fun)
Enumerable.reduce(tree, {:cont, acc}, fn
nil, acc ->
{:done, acc}

%{deleted?: true}, acc ->
{:cont, acc}

%{content: content}, acc ->
Enum.reduce_while(content, {:cont, acc}, fn c, {_, acc} ->
case fun.(c, acc) do
{:cont, _acc} = r -> {:cont, r}
{:halt, _acc} = r -> {:halt, r}
end
end)
end)
end

def reduce(_array, {:halt, acc}, _fun) do
Expand All @@ -267,7 +309,7 @@ defmodule Y.Type.Array do
{:suspended, acc, &reduce(array, &1, fun)}
end

def slice(_array) do
def slice(_) do
{:error, __MODULE__}
end
end
Expand Down
4 changes: 3 additions & 1 deletion lib/y/type/array/array_tree.ex
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,8 @@ defmodule Y.Type.Array.ArrayTree do

def first(%ArrayTree{ft: tree}), do: FingerTree.first(tree)
def last(%ArrayTree{ft: tree}), do: FingerTree.last(tree)
def rest(%ArrayTree{ft: tree} = array_tree), do: %{array_tree | ft: FingerTree.rest(tree)}
def butlast(%ArrayTree{ft: tree} = array_tree), do: %{array_tree | ft: FingerTree.butlast(tree)}

def length(%ArrayTree{ft: tree}) do
%Meter{len: len} = FingerTree.measure(tree)
Expand Down Expand Up @@ -448,7 +450,7 @@ defmodule Y.Type.Array.ArrayTree do
{:suspended, acc, &reduce(array, &1, fun)}
end

def slice(_array) do
def slice(_) do
{:error, __MODULE__}
end
end
Expand Down
28 changes: 27 additions & 1 deletion test/array_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ defmodule Y.ArrayTest do
|> Doc.get("array")

assert Enum.to_list(0..40//2) ==
Enum.map(array, fn %Item{content: [content]} -> content * 2 end)
Enum.map(array, fn c -> c * 2 end)
end

test "length + at" do
Expand Down Expand Up @@ -364,4 +364,30 @@ defmodule Y.ArrayTest do
# array[8] == 9
assert [0, 1, 2, 3, 4, 6] = Array.to_list(array)
end

test "enumerable protocol" do
{:ok, doc} = Doc.new(name: :doc_enumerable)
{:ok, array} = Doc.get_array(doc, "array")

assert [] = Enum.slice(array, 1..3)

assert {:ok, _} =
Doc.transact(doc, fn transaction ->
{:ok, array, transaction} = Array.put(array, transaction, 0, 0)
{:ok, transaction} = Array.delete(array, transaction, 0)
{:ok, array} = Doc.get(transaction, "array")
assert [] = Enum.slice(array, 1..3)

{:ok, array, transaction} =
Enum.reduce(1..9, Array.put(array, transaction, 0, 0), fn i, acc ->
Array.put(acc, i, i)
end)

{:ok, transaction} = Array.delete(array, transaction, 2)
{:ok, array} = Doc.get(transaction, "array")
assert [1, 3, 4] = Enum.slice(array, 1..3)

{:ok, transaction}
end)
end
end

0 comments on commit 59d914b

Please sign in to comment.