Skip to content

Instantly share code, notes, and snippets.

@redrabbit
Last active June 29, 2017 22:44
Show Gist options
  • Save redrabbit/e3060e2732e525f7134319bf6fc67472 to your computer and use it in GitHub Desktop.
Save redrabbit/e3060e2732e525f7134319bf6fc67472 to your computer and use it in GitHub Desktop.
Elixir mutable bucket via :ets
defmodule Bucket do
@moduledoc """
A mutable "bucket" implementing the `Access` behaviour.
"""
@behaviour Access
defstruct [:ets]
@type t :: %__MODULE__{ets: term}
@doc """
Returns a new empty bucket.
"""
@spec new() :: t
def new do
Map.new
table = :ets.new(__MODULE__, [:set, :protected])
struct(__MODULE__, ets: table)
end
#
# Callbacks
#
@doc false
def fetch(%__MODULE__{ets: table}, key) do
case :ets.lookup(table, key) do
[{^key, val}] ->
{:ok, val}
_else ->
:error
end
end
@doc false
def get(%__MODULE__{} = bucket, key, default) do
case fetch(bucket, key) do
{:ok, value} -> value
:error -> default
end
end
@doc false
def get_and_update(%__MODULE__{ets: table} = bucket, key, list) do
val = get(bucket, key, nil)
case list.(val) do
{ret_val, new_val} ->
:ets.insert(table, {key, new_val})
{ret_val, bucket}
:pop ->
:ets.delete(table, key)
{val, bucket}
end
end
@doc false
def pop(%__MODULE__{ets: table} = bucket, key) do
case :ets.take(table, key) do
[val] ->
{val, bucket}
[] ->
{nil, bucket}
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment