Skip to content

Commit

Permalink
dexts: use a protocol for Select and Match
Browse files Browse the repository at this point in the history
  • Loading branch information
meh committed Jul 12, 2014
1 parent 0c88826 commit bfdde5f
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 54 deletions.
79 changes: 29 additions & 50 deletions lib/dexts.ex
Original file line number Diff line number Diff line change
Expand Up @@ -183,73 +183,55 @@ defmodule Dexts do
:dets.foldr(fun, acc, table)
end

defmodule Selection do
@moduledoc """
Selection wraps an `dets:select` result, which may or may not contain a
continuation, in case of continuations you can access the next set of
values by calling `.next`.
"""

defmodule Select do
defstruct values: [], continuation: nil

@doc """
Get a Selection from the various select results.
"""
@spec new(:'$end_of_table' | list | { list, any }) :: t | nil
def new(value) do
case value do
:'$end_of_table' -> nil
[] -> nil
{ [], _ } -> nil

{ values, continuation } ->
%Selection{values: values, continuation: continuation}
%Select{values: values, continuation: continuation}

[_ | _] ->
%Selection{values: value}
%Select{values: value}
end
end

@doc """
Get the next set of values wrapped in another Selection, returns nil if
there are no more.
"""
@spec next(t) :: t | nil
def next(%Selection{continuation: nil}) do
nil
end
defimpl Dexts.Selection do
def next(%Select{continuation: nil}) do
nil
end

def next(%Selection{continuation: continuation}) do
new(:dets.select(continuation))
def next(%Select{continuation: continuation}) do
Select.new(:dets.select(continuation))
end

def values(%Select{values: values}) do
values
end
end
end

@doc """
Select terms in the given table using a match_spec, see `dets:select`.
"""
@spec select(table, any) :: Selection.t | nil
@spec select(table, any) :: Dexts.Selection.t | nil
def select(table, match_spec, options \\ [])

def select(table, match_spec, []) do
Selection.new(:dets.select(table, match_spec))
Select.new(:dets.select(table, match_spec))
end

def select(table, match_spec, limit: limit) do
Selection.new(:dets.select(table, match_spec, limit))
Select.new(:dets.select(table, match_spec, limit))
end

defmodule Match do
@moduledoc """
Match wraps an `dets:match` or `dets:match_object` result, which may or may
not contain a continuation, in case of continuations you can access the
next set of values by calling `.next`.
"""

defstruct values: [], continuation: nil, whole: false

@doc """
Get a Match from the various match results.
"""
def new(value, whole \\ false) do
case value do
:'$end_of_table' -> nil
Expand All @@ -264,28 +246,25 @@ defmodule Dexts do
end
end

@doc """
Get the next set of values wrapped in another Match, returns nil if there
are no more.
"""
@spec next(t) :: Match.t | nil
def next(%Match{continuation: nil}) do
nil
end
defimpl Dexts.Selection do
def next(%Match{continuation: nil}) do
nil
end

def next(%Match{whole: true, continuation: continuation}) do
new(:dets.match_object(continuation))
end
def next(%Match{whole: true, continuation: continuation}) do
Match.new(:dets.match_object(continuation))
end

def next(%Match{whole: false, continuation: continuation}) do
new(:dets.match(continuation))
def values(%Match{values: values}) do
values
end
end
end

@doc """
Match terms from the given table with the given pattern, see `dets:match`.
"""
@spec match(table, any) :: Match.t | nil
@spec match(table, any) :: Dexts.Selection.t | nil
def match(table, pattern) do
Match.new(:dets.match(table, pattern))
end
Expand All @@ -301,7 +280,7 @@ defmodule Dexts do
them.
* `:limit` the amount of elements to select at a time.
"""
@spec match(table, any | integer, Keyword.t | any) :: Match.t | nil
@spec match(table, any | integer, Keyword.t | any) :: Dexts.Selection.t | nil
def match(table, pattern, delete: true) do
:dets.match_delete(table, pattern)
end
Expand Down
8 changes: 4 additions & 4 deletions lib/dexts/dict.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

defmodule Dexts.Dict do
defstruct [:id, :type]

@opaque t :: %Dexts.Dict{}
alias __MODULE__, as: T

use Dict
Expand Down Expand Up @@ -196,7 +196,7 @@ defmodule Dexts.Dict do
@doc """
Select terms in the table using a match_spec, see `ets:select`.
"""
@spec select(t, any, Keyword.t) :: [any]
@spec select(t, any, Keyword.t) :: Dexts.Selection.t | nil
def select(%T{id: id}, match_spec, options \\ []) do
Dexts.select(id, match_spec, options)
end
Expand All @@ -205,15 +205,15 @@ defmodule Dexts.Dict do
Select terms in the table using a match_spec, traversing in reverse, see
`ets:select_reverse`.
"""
@spec reverse_select(t, any) :: [any]
@spec reverse_select(t, any) :: Dexts.Selection.t | nil
def reverse_select(%T{id: id}, match_spec, options \\ []) do
Dexts.reverse_select(id, match_spec, options)
end

@doc """
Match terms from the table with the given pattern, see `ets:match`.
"""
@spec match(t, any) :: Match.t | nil
@spec match(t, any) :: Dexts.Selection.t | nil
def match(%T{id: id}, pattern, options \\ []) do
Dexts.match(id, pattern, options)
end
Expand Down
22 changes: 22 additions & 0 deletions lib/dexts/selection.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
# Version 2, December 2004
#
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
#
# 0. You just DO WHAT THE FUCK YOU WANT TO.

defprotocol Dexts.Selection do
def next(self)
def values(self)
end

defimpl Dexts.Selection, for: Atom do
def next(nil) do
nil
end

def values(nil) do
[]
end
end

0 comments on commit bfdde5f

Please sign in to comment.