# `RDF.Dataset`
[🔗](https://github.com/rdf-elixir/rdf-ex/blob/v3.0.1/lib/rdf/model/dataset.ex#L1)

A set of `RDF.Graph`s.

It may have multiple named graphs and at most one unnamed ("default") graph.

`RDF.Dataset` implements:

- the `RDF.Data.Source` protocol
- Elixir's `Enumerable` protocol
- Elixir's `Collectable` protocol
- Elixir's `Inspect` protocol
- Elixir's `Access` behaviour

# `get_and_update_graph_fun`

```elixir
@type get_and_update_graph_fun() :: (RDF.Graph.t() -&gt; {RDF.Graph.t(), input()} | :pop)
```

# `graph_name`

```elixir
@type graph_name() :: RDF.IRI.t() | nil
```

# `input`

```elixir
@type input() :: RDF.Graph.input() | t()
```

# `t`

```elixir
@type t() :: %RDF.Dataset{
  graphs: %{required(graph_name()) =&gt; RDF.Graph.t()},
  name: graph_name()
}
```

# `update_graph_fun`

```elixir
@type update_graph_fun() :: (RDF.Graph.t() -&gt; {RDF.Graph.t()})
```

# `add`

```elixir
@spec add(t(), input(), keyword()) :: t()
```

Adds triples and quads to a `RDF.Dataset`.

The triples can be provided in any form accepted by `add/2`.

- as a single statement tuple
- an `RDF.Description`
- an `RDF.Graph`
- an `RDF.Dataset`
- or a list with any combination of the former

The `graph` option allows to set a different destination graph to which the
statements should be added, ignoring the graph context of given quads or the
name of given graphs in `input`.

Note: When the statements to be added are given as another `RDF.Dataset` and
a destination graph is set with the `graph` option, the descriptions of the
subjects in the different graphs are aggregated.

# `canonical_hash`

```elixir
@spec canonical_hash(
  t() | RDF.Graph.t(),
  keyword()
) :: binary()
```

Returns a hash of the canonical form of the given dataset.

This hash is computed as follows:

1. Compute the canonical form of the dataset according to the RDF Dataset Canonicalization spec
   using `canonicalize/1`.
2. Serialize this canonical dataset to N-Quads sorted by Unicode code point order.
3. Compute the SHA-256 of this N-Quads serialization.

Note that the data structure is not relevant for the canonical hash, i.e.
the same hash is generated for the same data regardless of whether it is
passed in an `RDF.Graph`, `RDF.Dataset` or `RDF.Description`.

## Options

- `:hash_algorithm` (default: `:sha256`): Allows to set the hash algorithm to be used in step 3.
  Any of the `:crypto.hash_algorithm()` values of Erlang's `:crypto` module are allowed.
  Note that this does NOT affect the hash function used during the

## Example

    iex> RDF.Dataset.new([{~B<foo>, EX.p(), ~B<bar>}, {~B<bar>, EX.p(), ~B<foo>}])
    ...> |> RDF.Dataset.canonical_hash()
    "053688e09a20a49acc3e1a5e6403c827b817eef9e4c90bfd71f2360e2a6446aa"

    iex> RDF.Graph.new([{~B<other>, EX.p(), ~B<bar>}, {~B<bar>, EX.p(), ~B<other>}])
    ...> |> RDF.Graph.canonical_hash()
    "053688e09a20a49acc3e1a5e6403c827b817eef9e4c90bfd71f2360e2a6446aa"

# `canonicalize`

```elixir
@spec canonicalize(
  t() | RDF.Graph.t(),
  keyword()
) :: t()
```

Canonicalizes the blank nodes of a dataset according to the RDF Dataset Canonicalization spec.

See the `RDF.Canonicalization` module documentation on available options.

## Example

    iex> RDF.Dataset.new([{~B<foo>, EX.p(), ~B<bar>}, {~B<bar>, EX.p(), ~B<foo>}])
    ...> |> RDF.Dataset.canonicalize()
    RDF.Dataset.new([{~B<c14n0>, EX.p(), ~B<c14n1>}, {~B<c14n1>, EX.p(), ~B<c14n0>}])

# `change_name`

```elixir
@spec change_name(t(), RDF.Statement.coercible_graph_name()) :: t()
```

Changes the dataset name of `dataset`.

# `default_graph`

```elixir
@spec default_graph(t()) :: RDF.Graph.t()
```

The default graph of a `RDF.Dataset`.

## Examples

    iex> RDF.Dataset.new([
    ...>   {EX.S1, EX.p1, EX.O1},
    ...>   {EX.S2, EX.p2, EX.O2, EX.Graph1},
    ...>   {EX.S1, EX.p2, EX.O3, EX.Graph2}])
    ...> |> RDF.Dataset.default_graph()
    Graph.new({EX.S1, EX.p1, EX.O1})

# `delete`

```elixir
@spec delete(t(), input(), keyword()) :: t()
```

Deletes statements from a `RDF.Dataset`.

The `graph` option allows to set a different destination graph from which the
statements should be deleted, ignoring the graph context of given quads or the
name of given graphs.

Note: When the statements to be deleted are given as another `RDF.Dataset`,
the dataset name must not match dataset name of the dataset from which the statements
are deleted. If you want to delete only datasets with matching names, you can
use `RDF.Data.delete/2`.

# `delete_default_graph`

```elixir
@spec delete_default_graph(t()) :: t()
```

Deletes the default graph.

# `delete_graph`

```elixir
@spec delete_graph(
  t(),
  RDF.Statement.graph_name() | [RDF.Statement.graph_name()] | nil
) :: t()
```

Deletes the given graph.

# `describes?`

```elixir
@spec describes?(t(), RDF.Statement.t(), RDF.Statement.coercible_graph_name() | nil) ::
  boolean()
```

Checks if a graph of a `RDF.Dataset` contains statements about the given resource.

## Examples

      iex> RDF.Dataset.new([{EX.S1, EX.p1, EX.O1}]) |> RDF.Dataset.describes?(EX.S1)
      true
      iex> RDF.Dataset.new([{EX.S1, EX.p1, EX.O1}]) |> RDF.Dataset.describes?(EX.S2)
      false

# `empty?`

```elixir
@spec empty?(t()) :: boolean()
```

Returns if the given `dataset` is empty.

Note: You should always prefer this over the use of `Enum.empty?/1` as it is significantly faster.

# `equal?`

```elixir
@spec equal?(t() | any(), t() | any()) :: boolean()
```

Checks if two `RDF.Dataset`s are equal.

Two `RDF.Dataset`s are considered to be equal if they contain the same triples
and have the same name.

# `fetch`

```elixir
@spec fetch(t(), RDF.Statement.graph_name() | nil) :: {:ok, RDF.Graph.t()} | :error
```

Fetches the `RDF.Graph` with the given name.

When a graph with the given name can not be found can not be found `:error` is returned.

## Examples

    iex> dataset = RDF.Dataset.new([{EX.S1, EX.P1, EX.O1, EX.Graph}, {EX.S2, EX.P2, EX.O2}])
    ...> RDF.Dataset.fetch(dataset, EX.Graph)
    {:ok, RDF.Graph.new({EX.S1, EX.P1, EX.O1}, name: EX.Graph)}
    iex> RDF.Dataset.fetch(dataset, nil)
    {:ok, RDF.Graph.new({EX.S2, EX.P2, EX.O2})}
    iex> RDF.Dataset.fetch(dataset, EX.Foo)
    :error

# `get`

```elixir
@spec get(t(), RDF.Statement.graph_name() | nil, RDF.Graph.t() | nil) ::
  RDF.Graph.t() | nil
```

Fetches the `RDF.Graph` with the given name.

When a graph with the given name can not be found can not be found the optionally
given default value or `nil` is returned

## Examples

    iex> dataset = RDF.Dataset.new([{EX.S1, EX.P1, EX.O1, EX.Graph}, {EX.S2, EX.P2, EX.O2}])
    ...> RDF.Dataset.get(dataset, EX.Graph)
    RDF.Graph.new({EX.S1, EX.P1, EX.O1}, name: EX.Graph)
    iex> RDF.Dataset.get(dataset, nil)
    RDF.Graph.new({EX.S2, EX.P2, EX.O2})
    iex> RDF.Dataset.get(dataset, EX.Foo)
    nil
    iex> RDF.Dataset.get(dataset, EX.Foo, :bar)
    :bar

# `get_and_update`

```elixir
@spec get_and_update(
  t(),
  RDF.Statement.graph_name() | nil,
  get_and_update_graph_fun()
) ::
  {RDF.Graph.t(), t()}
```

Gets and updates the graph with the given name, in a single pass.

Invokes the passed function on the `RDF.Graph` with the given name;
this function should return either `{graph_to_return, new_graph}` or `:pop`.

If the passed function returns `{graph_to_return, new_graph}`, the
return value of `get_and_update` is `{graph_to_return, new_dataset}` where
`new_dataset` is the input `Dataset` updated with `new_graph` for
the given name.

If the passed function returns `:pop` the graph with the given name is
removed and a `{removed_graph, new_dataset}` tuple gets returned.

## Examples

    iex> dataset = RDF.Dataset.new({EX.S, EX.P, EX.O, EX.Graph})
    ...> RDF.Dataset.get_and_update(dataset, EX.Graph, fn current_graph ->
    ...>     {current_graph, {EX.S, EX.P, EX.NEW}}
    ...>   end)
    {RDF.Graph.new({EX.S, EX.P, EX.O}, name: EX.Graph), RDF.Dataset.new({EX.S, EX.P, EX.NEW, EX.Graph})}

# `graph`

```elixir
@spec graph(t(), RDF.Statement.coercible_graph_name() | nil) :: RDF.Graph.t() | nil
```

The graph with given name.

# `graph_count`

```elixir
@spec graph_count(t()) :: non_neg_integer()
```

The number of graphs within a `RDF.Dataset`.

## Examples

    iex> RDF.Dataset.new([
    ...>   {EX.S1, EX.p1, EX.O1},
    ...>   {EX.S2, EX.p2, EX.O2},
    ...>   {EX.S1, EX.p2, EX.O3, EX.Graph}])
    ...> |> RDF.Dataset.graph_count()
    2

# `graph_names`

```elixir
@spec graph_names(t()) :: [RDF.IRI.t() | nil]
```

A list of all graph names within the dataset.

Note, that this includes `nil` when the dataset has a default graph.

## Examples

    iex> RDF.Dataset.new([
    ...>   {EX.S1, EX.p1, EX.O1},
    ...>   {EX.S2, EX.p2, EX.O2, EX.Graph1},
    ...>   {EX.S1, EX.p2, EX.O3, EX.Graph2}])
    ...> |> RDF.Dataset.graph_names()
    [nil, RDF.iri(EX.Graph1), RDF.iri(EX.Graph2)]

# `graphs`

```elixir
@spec graphs(t()) :: [RDF.Graph.t()]
```

A list of all graphs within the dataset.

# `include?`

```elixir
@spec include?(t(), input(), keyword()) :: boolean()
```

Checks if the given `input` statements exist within `dataset`.

The `graph` option allows to set a different destination graph in which the
statements should be checked, ignoring the graph context of given quads or the
name of given graphs.

## Examples

      iex> dataset = RDF.Dataset.new([
      ...>   {EX.S1, EX.p1, EX.O1, EX.Graph},
      ...>   {EX.S2, EX.p2, EX.O2},
      ...>   {EX.S1, EX.p2, EX.O3}])
      ...> RDF.Dataset.include?(dataset, {EX.S1, EX.p1, EX.O1, EX.Graph})
      true

# `intersection`

```elixir
@spec intersection(t(), t() | RDF.Graph.t() | RDF.Description.t() | input()) :: t()
```

Returns a new dataset that is the intersection of the given `dataset` with the given `data`.

The `data` can be given in any form an `RDF.Dataset` can be created from.

## Examples

    iex> RDF.Dataset.new([
    ...>   {EX.S1, EX.p(), [EX.O1, EX.O2]},
    ...>   {EX.S2, EX.p(), EX.O3, EX.Graph}
    ...> ])
    ...> |> RDF.Dataset.intersection([
    ...>     {EX.S1, EX.p(), EX.O2},
    ...>     {EX.S2, EX.p(), EX.O3}
    ...>   ])
    RDF.Dataset.new({EX.S1, EX.p(), EX.O2})

# `isomorphic?`

# `map`

```elixir
@spec map(t(), RDF.Statement.term_mapping()) :: map()
```

Returns a nested map of a `RDF.Dataset` where each element from its quads is mapped with the given function.

The function `fun` will receive a tuple `{statement_position, rdf_term}` where
`statement_position` is one of the atoms `:subject`, `:predicate`, `:object` or
`:graph_name` while `rdf_term` is the RDF term to be mapped. When the given function
returns `nil` this will be interpreted as an error and will become the overhaul
result of the `map/2` call.

## Examples

    iex> [
    ...>   {~I<http://example.com/S>, ~I<http://example.com/p>, ~L"Foo", ~I<http://example.com/Graph>},
    ...>   {~I<http://example.com/S>, ~I<http://example.com/p>, RDF.XSD.integer(42), }
    ...> ]
    ...> |> RDF.Dataset.new()
    ...> |> RDF.Dataset.map(fn
    ...>      {:graph_name, graph_name} ->
    ...>        graph_name
    ...>      {:predicate, predicate} ->
    ...>        predicate
    ...>        |> to_string()
    ...>        |> String.split("/")
    ...>        |> List.last()
    ...>        |> String.to_atom()
    ...>    {_, term} ->
    ...>      RDF.Term.value(term)
    ...>    end)
    %{
      ~I<http://example.com/Graph> => %{
        "http://example.com/S" => %{p: ["Foo"]}
      },
      nil => %{
        "http://example.com/S" => %{p: [42]}
      }
    }

# `name`

```elixir
@spec name(t()) :: RDF.Statement.graph_name()
```

Returns the dataset name IRI of `dataset`.

# `named_graphs`

```elixir
@spec named_graphs(t()) :: [RDF.Graph.t()]
```

The named graphs of a `RDF.Dataset`.

## Examples

    iex> RDF.Dataset.new([
    ...>   {EX.S1, EX.p1, EX.O1},
    ...>   {EX.S2, EX.p2, EX.O2, EX.Graph1},
    ...>   {EX.S1, EX.p2, EX.O3, EX.Graph2}])
    ...> |> RDF.Dataset.named_graphs()
    [
      Graph.new({EX.S2, EX.p2, EX.O2}, name: EX.Graph1),
      Graph.new({EX.S1, EX.p2, EX.O3}, name: EX.Graph2)
    ]

# `new`

```elixir
@spec new() :: t()
```

Creates an empty unnamed `RDF.Dataset`.

# `new`

```elixir
@spec new(input() | keyword()) :: t()
```

Creates an `RDF.Dataset`.

If a keyword list is given an empty dataset is created.
Otherwise, an unnamed dataset initialized with the given data is created.

See `new/2` for available arguments and the different ways to provide data.

## Examples

    RDF.Dataset.new(name: EX.GraphName)

    RDF.Dataset.new(init: {EX.S, EX.p, EX.O})

    RDF.Dataset.new({EX.S, EX.p, EX.O})

# `new`

```elixir
@spec new(
  input(),
  keyword()
) :: t()
```

Creates an `RDF.Dataset` initialized with data.

The initial RDF triples can be provided in any form accepted by `add/3`.

Available options:

- `name`: the name of the dataset to be created
- `init`: some data with which the dataset should be initialized; the data can be
  provided in any form accepted by `add/3` and above that also with a function returning
  the initialization data in any of these forms

# `pop`

```elixir
@spec pop(t()) :: {RDF.Statement.t() | nil, t()}
```

Pops an arbitrary statement from a `RDF.Dataset`.

# `pop`

```elixir
@spec pop(t(), RDF.Statement.coercible_graph_name()) :: {RDF.Graph.t() | nil, t()}
```

Pops the graph with the given name.

Removes the graph of the given `graph_name` from `dataset`.

Returns a tuple containing the graph of the given name
and the updated dataset without this graph.
`nil` is returned instead of the graph if `dataset` does
not contain a graph_name of the given `graph_name`.

## Examples

    iex> dataset = RDF.Dataset.new([
    ...>   {EX.S1, EX.P1, EX.O1, EX.Graph},
    ...>   {EX.S2, EX.P2, EX.O2}])
    ...> RDF.Dataset.pop(dataset, EX.Graph)
    {
      RDF.Graph.new({EX.S1, EX.P1, EX.O1}, name: EX.Graph),
      RDF.Dataset.new({EX.S2, EX.P2, EX.O2})
    }
    iex> RDF.Dataset.pop(dataset, EX.Foo)
    {nil, dataset}

# `prefixes`

```elixir
@spec prefixes(t()) :: RDF.PrefixMap.t() | nil
```

Returns the aggregated prefixes of all graphs of `dataset` as a `RDF.PrefixMap`.

# `put`

```elixir
@spec put(t(), input(), keyword()) :: t()
```

Adds statements to a `RDF.Dataset` overwriting existing statements with the subjects given in the `input` data.

By overwriting statements with the same subject, this function has a similar
semantics as `RDF.Graph.put/3`, if you want to replace whole graphs use
`put_graph/3` instead.

The `graph` option allows to set a different destination graph to which the
statements should be added, ignoring the graph context of given quads or the
name of given graphs in `input`.

Note: When the statements to be added are given as another `RDF.Dataset` and
a destination graph is set with the `graph` option, the descriptions of the
subjects in the different graphs are aggregated.

## Examples

    iex> dataset = RDF.Dataset.new({EX.S, EX.P1, EX.O1})
    ...> RDF.Dataset.put(dataset, {EX.S, EX.P2, EX.O2})
    RDF.Dataset.new({EX.S, EX.P2, EX.O2})
    iex> RDF.Dataset.put(dataset, {EX.S2, EX.P2, EX.O2})
    RDF.Dataset.new([{EX.S, EX.P1, EX.O1}, {EX.S2, EX.P2, EX.O2}])

# `put_graph`

```elixir
@spec put_graph(t(), input(), keyword()) :: t()
```

Adds new graphs to a `RDF.Dataset` overwriting any existing graphs with the same name.

The `graph` option allows to set a different destination graph to which the
statements should be added, ignoring the graph context of given quads or the
name of given graphs in `input`.

Note: When the statements to be added are given as another `RDF.Dataset` and
a destination graph is set with the `graph` option, the descriptions of the
subjects in the different graphs are aggregated.

# `put_properties`

```elixir
@spec put_properties(t(), input(), keyword()) :: t()
```

Adds statements to a `RDF.Dataset` and overwrites all existing statements with the same subject-predicate combinations given in the `input` data.

The `graph` option allows to set a different destination graph to which the
statements should be added, ignoring the graph context of given quads or the
name of given graphs in `input`.

Note: When the statements to be added are given as another `RDF.Dataset` and
a destination graph is set with the `graph` option, the descriptions of the
subjects in the different graphs are aggregated.

## Examples

    iex> dataset = RDF.Dataset.new({EX.S, EX.P1, EX.O1})
    ...> RDF.Dataset.put_properties(dataset, {EX.S, EX.P1, EX.O2})
    RDF.Dataset.new({EX.S, EX.P1, EX.O2})
    iex> RDF.Dataset.put_properties(dataset, {EX.S, EX.P2, EX.O2})
    RDF.Dataset.new([{EX.S, EX.P1, EX.O1}, {EX.S, EX.P2, EX.O2}])
    iex> RDF.Dataset.new([{EX.S1, EX.P1, EX.O1}, {EX.S2, EX.P2, EX.O2}])
    ...> |> RDF.Dataset.put_properties([{EX.S1, EX.P2, EX.O3}, {EX.S2, EX.P2, EX.O3}])
    RDF.Dataset.new([{EX.S1, EX.P1, EX.O1}, {EX.S1, EX.P2, EX.O3}, {EX.S2, EX.P2, EX.O3}])

# `quads`

```elixir
@spec quads(
  t(),
  keyword()
) :: [RDF.Quad.t()]
```

All statements within all graphs of a `RDF.Dataset` as quads.

When the optional `:filter_star` flag is set to `true` RDF-star statements with
a triple as subject or object will be filtered. The default value is `false`.

## Examples

      iex> RDF.Dataset.new([
      ...>   {EX.S1, EX.p1, EX.O1, EX.Graph},
      ...>   {EX.S2, EX.p2, EX.O2},
      ...>   {EX.S1, EX.p2, EX.O3}])
      ...> |> RDF.Dataset.quads()
      [{RDF.iri(EX.S1), RDF.iri(EX.p2), RDF.iri(EX.O3), nil},
       {RDF.iri(EX.S2), RDF.iri(EX.p2), RDF.iri(EX.O2), nil},
       {RDF.iri(EX.S1), RDF.iri(EX.p1), RDF.iri(EX.O1), RDF.iri(EX.Graph)}]

# `statement_count`

```elixir
@spec statement_count(t()) :: non_neg_integer()
```

The number of statements within a `RDF.Dataset`.

## Examples

    iex> RDF.Dataset.new([
    ...>   {EX.S1, EX.p1, EX.O1, EX.Graph},
    ...>   {EX.S2, EX.p2, EX.O2},
    ...>   {EX.S1, EX.p2, EX.O3}]) |>
    ...>   RDF.Dataset.statement_count()
    3

# `statements`

```elixir
@spec statements(
  t(),
  keyword()
) :: [RDF.Statement.t()]
```

All statements within all graphs of a `RDF.Dataset`.

While the statements of named graphs are returned as quad tuples, the statements
of the default graph are returned as triples. If you want to get quads or triples
uniformly, use the `quads/2` resp. `triples/2` functions instead.

When the optional `:filter_star` flag is set to `true` RDF-star statements with
a triple as subject or object will be filtered. The default value is `false`.

## Examples

      iex> RDF.Dataset.new([
      ...>   {EX.S1, EX.p1, EX.O1, EX.Graph},
      ...>   {EX.S2, EX.p2, EX.O2},
      ...>   {EX.S1, EX.p2, EX.O3}])
      ...> |> RDF.Dataset.statements()
      [{RDF.iri(EX.S1), RDF.iri(EX.p2), RDF.iri(EX.O3)},
       {RDF.iri(EX.S2), RDF.iri(EX.p2), RDF.iri(EX.O2)},
       {RDF.iri(EX.S1), RDF.iri(EX.p1), RDF.iri(EX.O1), RDF.iri(EX.Graph)}]

# `subjects`

The set of all subjects used in the statement within all graphs of a `RDF.Dataset`.

## Examples

    iex> RDF.Dataset.new([
    ...>   {EX.S1, EX.p1, EX.O1, EX.Graph},
    ...>   {EX.S2, EX.p2, EX.O2},
    ...>   {EX.S1, EX.p2, EX.O3}]) |>
    ...>   RDF.Dataset.subjects()
    MapSet.new([RDF.iri(EX.S1), RDF.iri(EX.S2)])

# `triples`

```elixir
@spec triples(
  t(),
  keyword()
) :: [RDF.Triple.t()]
```

All statements within all graphs of a `RDF.Dataset` as triples.

When the optional `:filter_star` flag is set to `true` RDF-star statements with
a triple as subject or object will be filtered. The default value is `false`.

Note: When a triple is present in multiple graphs it will be present in the resulting
list of triples multiple times for performance reasons. If you want to get a list with
unique triples, you'll have to apply `Enum.uniq/1` on the result.

## Examples

      iex> RDF.Dataset.new([
      ...>   {EX.S1, EX.p1, EX.O1, EX.Graph},
      ...>   {EX.S2, EX.p2, EX.O2},
      ...>   {EX.S1, EX.p2, EX.O3}])
      ...> |> RDF.Dataset.triples()
      [{RDF.iri(EX.S1), RDF.iri(EX.p2), RDF.iri(EX.O3)},
       {RDF.iri(EX.S2), RDF.iri(EX.p2), RDF.iri(EX.O2)},
       {RDF.iri(EX.S1), RDF.iri(EX.p1), RDF.iri(EX.O1)}]

# `update`

```elixir
@spec update(
  t(),
  RDF.Statement.graph_name(),
  RDF.Graph.input() | nil,
  update_graph_fun()
) :: t()
```

Updates a graph in `dataset` with the given function.

If `graph_name` is present in `dataset`, `fun` is invoked with argument `graph`
and its result is used as the new graph with the given `graph_name`.
If `graph_name` is not present in `dataset`, `initial` is inserted with the
given `graph_name`. If no `initial` value is given, the `dataset` remains unchanged.
If `nil` is returned by `fun`, the respective graph will be removed from `dataset`.

The initial value and the returned values by the update function will be
coerced to proper RDF graphs before added. If the initial or returned
graph is a `RDF.Graph` with another graph name, it will still be added
using the given `graph_name`.

## Examples

    iex> RDF.Dataset.new({EX.S, EX.p, EX.O, EX.Graph})
    ...> |> RDF.Dataset.update(EX.Graph,
    ...>      fn graph -> RDF.Graph.add(graph, {EX.S, EX.p, EX.O2})
    ...>    end)
    RDF.Dataset.new([{EX.S, EX.p, EX.O, EX.Graph}, {EX.S, EX.p, EX.O2, EX.Graph}])

    iex> RDF.Dataset.new()
    ...> |> RDF.Dataset.update(EX.Graph, RDF.Graph.new({EX.S, EX.p, EX.O}),
    ...>      fn graph -> RDF.Graph.add(graph, {EX.S, EX.p, EX.O2})
    ...>    end)
    RDF.Dataset.new([{EX.S, EX.p, EX.O, EX.Graph}])

# `update_all_graphs`

Updates all graphs in `dataset` with the given function.

The same behaviour as described in `RDF.Dataset.update/4` apply.
If `nil` is returned by `fun`, the respective graph will be removed from `dataset`.
The returned values by the update function will be coerced to proper RDF graphs before added.
If the returned graph is a `RDF.Graph` with another graph name, it will still be added
using the old graph name.

## Examples

    iex> RDF.Dataset.new([{EX.S1, EX.p1, EX.O1}, {EX.S2, EX.p2, EX.O2, EX.Graph}])
    ...> |> RDF.Dataset.update_all_graphs(&(RDF.Graph.add_prefixes(&1, ex: EX )))
    [
      RDF.Graph.new({EX.S1, EX.p1, EX.O1}, prefixes: [ex: EX]),
      RDF.Graph.new({EX.S2, EX.p2, EX.O2}, prefixes: [ex: EX], name: EX.Graph)
    ] |> RDF.Dataset.new()

# `values`

```elixir
@spec values(
  t(),
  keyword()
) :: map()
```

Returns a nested map of the native Elixir values of a `RDF.Dataset`.

When a `:context` option is given with a `RDF.PropertyMap`, predicates will
be mapped to the terms defined in the `RDF.PropertyMap`, if present.

## Examples

    iex> [
    ...>   {~I<http://example.com/S>, ~I<http://example.com/p>, ~L"Foo", ~I<http://example.com/Graph>},
    ...>   {~I<http://example.com/S>, ~I<http://example.com/p>, RDF.XSD.integer(42), }
    ...> ]
    ...> |> RDF.Dataset.new()
    ...> |> RDF.Dataset.values()
    %{
      "http://example.com/Graph" => %{
        "http://example.com/S" => %{"http://example.com/p" => ["Foo"]}
      },
      nil => %{
        "http://example.com/S" => %{"http://example.com/p" => [42]}
      }
    }

# `who_describes`

```elixir
@spec who_describes(t(), RDF.Statement.coercible_subject()) :: [RDF.Graph.t()]
```

Returns the names of all graphs of a `RDF.Dataset` containing statements about the given subject.

## Examples
      iex> dataset = RDF.Dataset.new([
      ...>   {EX.S1, EX.p, EX.O},
      ...>   {EX.S2, EX.p, EX.O},
      ...>   {EX.S1, EX.p, EX.O, EX.Graph1},
      ...>   {EX.S2, EX.p, EX.O, EX.Graph2}])
      ...> RDF.Dataset.who_describes(dataset, EX.S1)
      [nil, RDF.iri(EX.Graph1)]

---

*Consult [api-reference.md](api-reference.md) for complete listing*
