ets v0.5.0 Ets.Bag View Source

Module for creating and interacting with :ets tables of the type :bag and :duplicate_bag.

Bags contain “records” which are tuples. Bags are configured with a key position via the keypos: integer option. If not specified, the default key position is 1. The element of the tuple record at the key position is that records key. For example, setting the keypos to 2 means the key of an inserted record {:a, :b} is :b:

iex> {:ok, bag} = Bag.new(keypos: 2)
iex> Bag.add!(bag, {:a, :b})
iex> Bag.lookup(bag, :a)
{:ok, []}
iex> Bag.lookup(bag, :b)
{:ok, [{:a, :b}]}

When a record is added to the table with add_new will only add the record if a matching key doesn’t already exist.

Examples

iex> {:ok, bag} = Bag.new()
iex> Bag.add_new!(bag, {:a, :b, :c})
iex> Bag.to_list!(bag)
[{:a, :b, :c}]
iex> Bag.add_new!(bag, {:d, :e, :f})
iex> Bag.to_list!(bag)
[{:d, :e, :f}, {:a, :b, :c}]
iex> Bag.add_new!(bag, {:a, :g, :h})
iex> Bag.to_list!(bag)
[{:d, :e, :f}, {:a, :b, :c}]

add and add_new take either a single tuple or a list of tuple records. When adding multiple records, they are added in an atomic an isolated manner. add_new doesn’t add any records if any of the new keys already exist in the bag.

By default, Bags allow duplicate records (each element of the tuple record is identical). To prevent duplicate records, set the duplicate: false opt when creating the Bag (if you want to prevent duplicate keys, use an Ets.Set instead). Note that duplicate: false will increase the time it takes to add records as the table must be checked for duplicates prior to insert. duplicate: true maps to the :ets table type :duplicate_bag, duplicate: false maps to :bag.

Link to this section Summary

Functions

Same as add/3 but unwraps or raises on error

Adds tuple record or list of tuple records to table

Same as add_new/2 but unwraps or raises on error

Same as add/2 but doesn’t add any records if one of the given keys already exists

Same as delete/1 but unwraps or raises on error

Same as delete/2 but unwraps or raises on error

Deletes specified Bag

Deletes record with specified key in specified Bag

Same as delete_all/1 but unwraps or raises on error

Deletes all records in specified Bag

Same as get_table/1 but unwraps or raises on error

Returns underlying :ets table reference

Same as has_key/2 but unwraps or raises on error

Determines if specified key exists in specified bag

Same as info/1 but unwraps or raises on error

Returns information on the bag

Same as lookup/3 but unwraps or raises on error

Returns list of records with specified key

Same as lookup_element/3 but unwraps or raises on error

Returns list of elements in specified position of records with specified key

Same as match/1 but unwraps or raises on error

Same as match/2 but unwraps or raises on error

Same as match/3 but unwraps or raises on error

Matches next bag of records from a match/3 or match/1 continuation

Returns records in the Bag that match the specified pattern

Same as match/2 but limits number of results to the specified limit

Same as new/1 but unwraps or raises on error

Creates new bag module with the specified options

Same as select/2 but unwraps or raises on error

Returns records in the specified Bag that match the specified match specification

Same as select_delete/2 but unwraps or raises on error

Deletes records in the specified Bag that match the specified match specification

Same as to_list/1 but unwraps or raises on error

Returns contents of table as a list

Same as wrap_existing/1 but unwraps or raises on error

Wraps an existing :ets :bag or :duplicate_bag in a Bag struct

Link to this section Types

Link to this type bag_options() View Source
bag_options() :: [Ets.Base.option() | {:duplicate, boolean()}]
Link to this type t() View Source
t() :: %Ets.Bag{
  duplicate: boolean(),
  info: keyword(),
  table: Ets.table_reference()
}

Link to this section Functions

Link to this function add!(bag, record_or_records) View Source
add!(Ets.Bag.t(), tuple() | [tuple()]) :: Ets.Bag.t()

Same as add/3 but unwraps or raises on error.

Link to this function add(bag, record) View Source
add(Ets.Bag.t(), tuple() | [tuple()]) :: {:ok, Ets.Bag.t()} | {:error, any()}

Adds tuple record or list of tuple records to table.

If Bag has duplicate: false, will overwrite duplicate records (full tuple must match, not just key).

Inserts multiple records in an atomic and isolated manner.

Examples

iex> {:ok, bag} = Bag.new()
iex> {:ok, _} = Bag.add(bag, [{:a, :b, :c}, {:d, :e, :f}])
iex> {:ok, _} = Bag.add(bag, {:a, :h, :i})
iex> {:ok, _} = Bag.add(bag, {:d, :x, :y})
iex> {:ok, _} = Bag.add(bag, {:d, :e, :f})
iex> Bag.to_list(bag)
{:ok, [{:d, :e, :f}, {:d, :x, :y}, {:d, :e, :f}, {:a, :b, :c}, {:a, :h, :i}]}

iex> {:ok, bag} = Bag.new(duplicate: false)
iex> {:ok, _} = Bag.add(bag, [{:a, :b, :c}, {:d, :e, :f}])
iex> {:ok, _} = Bag.add(bag, {:a, :h, :i})
iex> {:ok, _} = Bag.add(bag, {:d, :x, :y})
iex> {:ok, _} = Bag.add(bag, {:d, :e, :f}) # won't insert due to duplicate: false
iex> Bag.to_list(bag)
{:ok, [{:d, :e, :f}, {:d, :x, :y}, {:a, :b, :c}, {:a, :h, :i}]}
Link to this function add_new!(bag, record_or_records) View Source
add_new!(Ets.Bag.t(), tuple() | [tuple()]) :: Ets.Bag.t()

Same as add_new/2 but unwraps or raises on error.

Link to this function add_new(bag, record) View Source
add_new(Ets.Bag.t(), tuple() | [tuple()]) ::
  {:ok, Ets.Bag.t()} | {:error, any()}

Same as add/2 but doesn’t add any records if one of the given keys already exists.

Examples

iex> bag = Bag.new!()
iex> {:ok, _} = Bag.add_new(bag, [{:a, :b, :c}, {:d, :e, :f}])
iex> {:ok, _} = Bag.add_new(bag, [{:a, :x, :y}, {:g, :h, :i}]) # skips due to duplicate :a key
iex> {:ok, _} = Bag.add_new(bag, {:d, :z, :zz}) # skips due to duplicate :d key
iex> Bag.to_list!(bag)
[{:d, :e, :f}, {:a, :b, :c}]

Same as delete/1 but unwraps or raises on error.

Link to this function delete!(bag, key) View Source
delete!(Ets.Bag.t(), any()) :: Ets.Bag.t()

Same as delete/2 but unwraps or raises on error.

Link to this function delete(bag) View Source
delete(Ets.Bag.t()) :: {:ok, Ets.Bag.t()} | {:error, any()}

Deletes specified Bag.

Examples

iex> {:ok, bag} = Bag.new()
iex> {:ok, _} = Bag.info(bag, true)
iex> {:ok, _} = Bag.delete(bag)
iex> Bag.info(bag, true)
{:error, :table_not_found}
Link to this function delete(bag, key) View Source
delete(Ets.Bag.t(), any()) :: {:ok, Ets.Bag.t()} | {:error, any()}

Deletes record with specified key in specified Bag.

Examples

iex> bag = Bag.new!()
iex> Bag.add(bag, {:a, :b, :c})
iex> Bag.delete(bag, :a)
iex> Bag.lookup!(bag, :a)
[]
Link to this function delete_all!(bag) View Source
delete_all!(Ets.Bag.t()) :: Ets.Bag.t()

Same as delete_all/1 but unwraps or raises on error.

Link to this function delete_all(bag) View Source
delete_all(Ets.Bag.t()) :: {:ok, Ets.Bag.t()} | {:error, any()}

Deletes all records in specified Bag.

Examples

iex> bag = Bag.new!()
iex> bag
iex> |> Bag.add!({:a, :b, :c})
iex> |> Bag.add!({:b, :b, :c})
iex> |> Bag.add!({:c, :b, :c})
iex> |> Bag.to_list!()
[{:c, :b, :c}, {:b, :b, :c}, {:a, :b, :c}]
iex> Bag.delete_all(bag)
iex> Bag.to_list!(bag)
[]

Same as get_table/1 but unwraps or raises on error

Returns underlying :ets table reference.

For use in functions that are not yet implemented. If you find yourself using this, please consider submitting a PR to add the necessary function to Ets.

Examples

iex> bag = Bag.new!(name: :my_ets_table)
iex> {:ok, table} = Bag.get_table(bag)
iex> info = :ets.info(table)
iex> info[:name]
:my_ets_table
Link to this function has_key!(bag, key) View Source
has_key!(Ets.Bag.t(), any()) :: boolean()

Same as has_key/2 but unwraps or raises on error.

Link to this function has_key(bag, key) View Source
has_key(Ets.Bag.t(), any()) :: {:ok, boolean()} | {:error, any()}

Determines if specified key exists in specified bag.

Examples

iex> bag = Bag.new!()
iex> Bag.has_key(bag, :key)
{:ok, false}
iex> Bag.add(bag, {:key, :value})
iex> Bag.has_key(bag, :key)
{:ok, true}
Link to this function info!(bag, force_update \\ false) View Source
info!(Ets.Bag.t(), boolean()) :: keyword()

Same as info/1 but unwraps or raises on error.

Link to this function info(bag, force_update \\ false) View Source
info(Ets.Bag.t(), boolean()) :: {:ok, keyword()} | {:error, any()}

Returns information on the bag.

Second parameter forces updated information from ets, default (false) uses in-struct cached information. Force should be used when requesting size and memory.

Examples

iex> {:ok, bag} = Bag.new(duplicate: false, keypos: 3, read_concurrency: true, compressed: false)
iex> {:ok, info} = Bag.info(bag)
iex> info[:read_concurrency]
true
iex> {:ok, _} = Bag.add(bag, {:a, :b, :c})
iex> {:ok, info} = Bag.info(bag)
iex> info[:size]
0
iex> {:ok, info} = Bag.info(bag, true)
iex> info[:size]
1
Link to this function lookup!(bag, key) View Source
lookup!(Ets.Bag.t(), any()) :: [tuple()]

Same as lookup/3 but unwraps or raises on error.

Link to this function lookup(bag, key) View Source
lookup(Ets.Bag.t(), any()) :: {:ok, [tuple()]} | {:error, any()}

Returns list of records with specified key.

Examples

iex> Bag.new!()
iex> |> Bag.add!({:a, :b, :c})
iex> |> Bag.add!({:d, :e, :f})
iex> |> Bag.add!({:d, :e, :g})
iex> |> Bag.lookup(:d)
{:ok, [{:d, :e, :f}, {:d, :e, :g}]}
Link to this function lookup_element!(bag, key, pos) View Source
lookup_element!(Ets.Bag.t(), any(), non_neg_integer()) :: [any()]

Same as lookup_element/3 but unwraps or raises on error.

Link to this function lookup_element(bag, key, pos) View Source
lookup_element(Ets.Bag.t(), any(), non_neg_integer()) ::
  {:ok, [any()]} | {:error, any()}

Returns list of elements in specified position of records with specified key.

Examples

iex> Bag.new!()
iex> |> Bag.add!({:a, :b, :c})
iex> |> Bag.add!({:d, :e, :f})
iex> |> Bag.add!({:d, :h, :i})
iex> |> Bag.lookup_element(:d, 2)
{:ok, [:e, :h]}
Link to this function match!(continuation) View Source
match!(any()) :: {[tuple()], any() | :end_of_table}

Same as match/1 but unwraps or raises on error.

Same as match/2 but unwraps or raises on error.

Link to this function match!(bag, pattern, limit) View Source
match!(Ets.Bag.t(), Ets.match_pattern(), non_neg_integer()) ::
  {[tuple()], any() | :end_of_table}

Same as match/3 but unwraps or raises on error.

Link to this function match(continuation) View Source
match(any()) :: {:ok, {[tuple()], any() | :end_of_table}} | {:error, any()}

Matches next bag of records from a match/3 or match/1 continuation.

Examples

iex> bag = Bag.new!()
iex> Bag.add!(bag, [{:a, :b, :c, :d}, {:e, :b, :f, :g}, {:h, :b, :i, :j}])
iex> {:ok, {results, continuation}} = Bag.match(bag, {:"$1", :b, :"$2", :_}, 2)
iex> results
[[:e, :f], [:a, :c]]
iex> {:ok, {records2, continuation2}} = Bag.match(continuation)
iex> records2
[[:h, :i]]
iex> continuation2
:end_of_table
Link to this function match(bag, pattern) View Source
match(Ets.Bag.t(), Ets.match_pattern()) :: {:ok, [tuple()]} | {:error, any()}

Returns records in the Bag that match the specified pattern.

For more information on the match pattern, see the erlang documentation

Examples

iex> Bag.new!()
iex> |> Bag.add!([{:a, :b, :c, :d}, {:e, :c, :f, :g}, {:h, :b, :i, :j}])
iex> |> Bag.match({:"$1", :b, :"$2", :_})
{:ok, [[:h, :i], [:a, :c]]}
Link to this function match(bag, pattern, limit) View Source
match(Ets.Bag.t(), Ets.match_pattern(), non_neg_integer()) ::
  {:ok, {[tuple()], any() | :end_of_table}} | {:error, any()}

Same as match/2 but limits number of results to the specified limit.

Examples

iex> bag = Bag.new!()
iex> Bag.add!(bag, [{:a, :b, :c, :d}, {:e, :b, :f, :g}, {:h, :b, :i, :j}])
iex> {:ok, {results, _continuation}} = Bag.match(bag, {:"$1", :b, :"$2", :_}, 2)
iex> results
[[:e, :f], [:a, :c]]

Same as new/1 but unwraps or raises on error.

Link to this function new(opts \\ []) View Source
new(bag_options()) :: {:error, any()} | {:ok, Ets.Bag.t()}

Creates new bag module with the specified options.

Note that the underlying :ets table will be attached to the process that calls new and will be destroyed if that process dies.

Possible options:

  • name: when specified, creates a named table with the specified name
  • duplicate: when true, allows multiple identical records. (default true)
  • protection: :private, :protected, :public (default :protected)
  • heir: :none | {heir_pid, heir_data} (default :none)
  • keypos: integer (default 1)
  • read_concurrency: boolean (default false)
  • write_concurrency: boolean (default false)
  • compressed: boolean (default false)

Examples

iex> {:ok, bag} = Bag.new(duplicate: false, keypos: 3, read_concurrency: true, compressed: false)
iex> Bag.info!(bag)[:read_concurrency]
true

# Named :ets tables via the name keyword
iex> {:ok, bag} = Bag.new(name: :my_ets_table)
iex> Bag.info!(bag)[:name]
:my_ets_table

Same as select/2 but unwraps or raises on error.

Link to this function select(bag, spec) View Source
select(Ets.Bag.t(), Ets.match_spec()) :: {:ok, [tuple()]} | {:error, any()}

Returns records in the specified Bag that match the specified match specification.

For more information on the match specification, see the erlang documentation

Examples

iex> Bag.new!()
iex> |> Bag.add!([{:a, :b, :c, :d}, {:e, :c, :f, :g}, {:h, :b, :i, :j}])
iex> |> Bag.select([{{:"$1", :b, :"$2", :_},[],[:"$$"]}])
{:ok, [[:h, :i], [:a, :c]]}
Link to this function select_delete!(bag, spec) View Source
select_delete!(Ets.Bag.t(), Ets.match_spec()) :: [tuple()]

Same as select_delete/2 but unwraps or raises on error.

Link to this function select_delete(bag, spec) View Source
select_delete(Ets.Bag.t(), Ets.match_spec()) ::
  {:ok, [tuple()]} | {:error, any()}

Deletes records in the specified Bag that match the specified match specification.

For more information on the match specification, see the erlang documentation

Examples

iex> bag = Bag.new!()
iex> bag
iex> |> Bag.add!([{:a, :b, :c, :d}, {:e, :c, :f, :g}, {:h, :b, :c, :h}])
iex> |> Bag.select_delete([{{:"$1", :b, :"$2", :_},[{:"==", :"$2", :c}],[true]}])
{:ok, 2}
iex> Bag.to_list!(bag)
[{:e, :c, :f, :g}]
Link to this function to_list!(bag) View Source
to_list!(Ets.Bag.t()) :: [tuple()]

Same as to_list/1 but unwraps or raises on error.

Link to this function to_list(bag) View Source
to_list(Ets.Bag.t()) :: {:ok, [tuple()]} | {:error, any()}

Returns contents of table as a list.

Examples

iex> Bag.new!()
iex> |> Bag.add!({:a, :b, :c})
iex> |> Bag.add!({:d, :e, :f})
iex> |> Bag.add!({:d, :e, :f})
iex> |> Bag.to_list()
{:ok, [{:d, :e, :f}, {:d, :e, :f}, {:a, :b, :c}]}
Link to this function wrap_existing!(table_identifier) View Source
wrap_existing!(Ets.table_identifier()) :: Ets.Bag.t()

Same as wrap_existing/1 but unwraps or raises on error.

Link to this function wrap_existing(table_identifier) View Source
wrap_existing(Ets.table_identifier()) :: {:ok, Ets.Bag.t()} | {:error, any()}

Wraps an existing :ets :bag or :duplicate_bag in a Bag struct.

Examples

iex> :ets.new(:my_ets_table, [:bag, :named_table])
iex> {:ok, bag} = Bag.wrap_existing(:my_ets_table)
iex> Bag.info!(bag)[:name]
:my_ets_table