Functions for working with RDF data structures.
This module provides a rich API for RDF data structures built on top of
the minimal RDF.Data.Source protocol, similar to how Elixir's Enum
module builds on the Enumerable protocol.
Summary
Functions
Returns the count of primary elements relative to the structure type.
Returns the default graph from the RDF data structure.
Deletes matching statements from the data structure.
Returns true if the data describes the given subject.
Returns the description of a specific subject in the RDF data structure.
Returns the description of a specific subject, or a default value if not found.
Returns all descriptions in the data structure.
Invokes the given function for each statement in the data structure.
Returns true if the given RDF data structure is empty.
Checks equality of two data structures.
Filters statements in the data structure based on a predicate function.
Returns a specific graph from the RDF data structure.
Returns a specific graph from the RDF data structure, or a default value if not found.
Returns the count of graphs in the RDF data structure.
Returns all graph names in the data structure.
Returns all graphs in the data structure.
Checks if data includes the given statements.
Maps a transformation function over all statements in the data structure.
Transforms statements and accumulates a value in a single pass.
Merges a list of data structures and/or statements into a single structure.
Merges two data structures with automatic structural promotion.
Returns all unique resource objects in the data structure.
Returns all unique object terms in the data structure.
Returns all unique object terms in the data structure matching the filter function.
Removes and returns one statement from the RDF data structure.
Returns the count of unique predicates in the data structure.
Returns all unique predicates in the data structure.
Returns all unique predicates in the data structure matching the filter function.
Returns all statements as quads.
Reduces the RDF data structure using the given function without an initial accumulator.
Reduces the RDF data structure using the given function.
Reduces the RDF data structure using the given function with early termination support.
Rejects statements in the data structure based on a predicate function.
Returns all unique resources (non-literal terms) in the data structure.
Returns the count of statements in the RDF data structure.
Returns all statements in the data structure.
Returns the count of unique subjects in the RDF data structure.
Returns all unique subjects in the data structure.
Returns all unique subjects in the data structure matching the filter function.
Takes the first amount statements from the RDF data structure.
Converts the RDF data structure to a dataset.
Converts the RDF data structure to a graph.
Returns all statements as triples.
Functions
@spec count(RDF.Data.Source.t()) :: non_neg_integer()
Returns the count of primary elements relative to the structure type.
This provides a consistent "size" metric that is meaningful for each structure level.
:description: counts predicates (with non-empty object sets):graph: counts subjects (descriptions):dataset: counts graphs
Examples
iex> desc = EX.S |> EX.p(EX.O1) |> EX.q(EX.O2)
iex> RDF.Data.count(desc)
2 # 2 predicates
iex> graph = RDF.Graph.new([{EX.S1, EX.p, EX.O}, {EX.S2, EX.p, EX.O}])
iex> RDF.Data.count(graph)
2 # 2 subjects
iex> dataset = RDF.Dataset.new([{EX.S, EX.p, EX.O, EX.G1}, {EX.S, EX.p, EX.O, EX.G2}])
iex> RDF.Data.count(dataset)
2 # 2 graphs
@spec default_graph(RDF.Data.Source.t()) :: RDF.Data.Source.t()
Returns the default graph from the RDF data structure.
Examples
iex> desc = EX.S |> EX.p(EX.O)
iex> RDF.Data.default_graph(desc)
RDF.graph({EX.S, EX.p, EX.O})
iex> dataset = RDF.dataset([{EX.S, EX.p, EX.O, nil}])
iex> RDF.Data.default_graph(dataset)
RDF.graph({EX.S, EX.p, EX.O})
iex> dataset = RDF.dataset([{EX.S, EX.p, EX.O, EX.Graph1}])
iex> RDF.Data.default_graph(dataset)
RDF.graph()
@spec delete( RDF.Data.Source.t(), RDF.Statement.t() | [RDF.Statement.t()] | RDF.Data.Source.t() ) :: RDF.Data.Source.t()
Deletes matching statements from the data structure.
Returns a new data structure with the specified statements removed. The resulting structure maintains the same type and metadata (like graph names) as the original.
Examples
iex> graph = RDF.graph([{EX.S1, EX.p, EX.O1}, {EX.S2, EX.p, EX.O2}])
iex> RDF.Data.delete(graph, {EX.S1, EX.p, EX.O1})
RDF.graph({EX.S2, EX.p, EX.O2})
iex> graph = RDF.graph([{EX.S1, EX.p, EX.O1}, {EX.S2, EX.p, EX.O2}])
iex> RDF.Data.delete(graph, [{EX.S1, EX.p, EX.O1}, {EX.S2, EX.p, EX.O2}])
RDF.graph()
iex> graph = RDF.graph([{EX.S1, EX.p, EX.O1}, {EX.S2, EX.p, EX.O2}])
iex> RDF.Data.delete(graph, EX.S1 |> EX.p(EX.O1))
RDF.graph({EX.S2, EX.p, EX.O2})
@spec describes?(RDF.Data.Source.t(), RDF.Resource.coercible()) :: boolean()
Returns true if the data describes the given subject.
Checks if any statements with the given subject exist in the data structure.
Examples
iex> graph = RDF.graph([{EX.Alice, EX.knows, EX.Bob}])
iex> RDF.Data.describes?(graph, EX.Alice)
true
iex> graph = RDF.graph([{EX.Alice, EX.knows, EX.Bob}])
iex> RDF.Data.describes?(graph, EX.Unknown)
false
@spec description(RDF.Data.Source.t(), RDF.Resource.coercible()) :: RDF.Data.Source.t()
Returns the description of a specific subject in the RDF data structure.
If the subject doesn't exist, an empty description for that subject is returned.
Use description/3 to provide a custom default value.
Examples
iex> graph = RDF.graph([{EX.Alice, EX.knows, EX.Bob}])
iex> RDF.Data.description(graph, EX.Alice)
EX.Alice |> EX.knows(EX.Bob)
iex> graph = RDF.graph([{EX.Alice, EX.knows, EX.Bob}])
iex> RDF.Data.description(graph, EX.Charlie)
RDF.description(EX.Charlie)
@spec description(RDF.Data.Source.t(), RDF.Resource.coercible(), default) :: RDF.Data.Source.t() | default when default: term()
Returns the description of a specific subject, or a default value if not found.
Examples
iex> graph = RDF.graph([{EX.Alice, EX.knows, EX.Bob}])
iex> RDF.Data.description(graph, EX.Alice, nil)
EX.Alice |> EX.knows(EX.Bob)
iex> graph = RDF.graph([{EX.Alice, EX.knows, EX.Bob}])
iex> RDF.Data.description(graph, EX.Charlie, nil)
nil
iex> graph = RDF.graph([{EX.Alice, EX.knows, EX.Bob}])
iex> RDF.Data.description(graph, EX.Charlie, :not_found)
:not_found
@spec descriptions(RDF.Data.Source.t()) :: [RDF.Data.Source.t()]
Returns all descriptions in the data structure.
Examples
iex> graph = RDF.graph([{EX.S1, EX.p(), EX.O1}, {EX.S2, EX.p(), EX.O2}])
iex> RDF.Data.descriptions(graph)
[EX.p(EX.S1, EX.O1), EX.p(EX.S2, EX.O2)]
iex> dataset = RDF.dataset([{EX.S1, EX.p(), EX.O1, nil}, {EX.S2, EX.p(), EX.O2, EX.G}, {EX.S3, EX.p(), EX.O3, EX.G}])
iex> RDF.Data.descriptions(dataset)
[EX.p(EX.S1, EX.O1), EX.p(EX.S2, EX.O2), EX.p(EX.S3, EX.O3)]
@spec each(RDF.Data.Source.t(), (RDF.Statement.t() -> any())) :: :ok
Invokes the given function for each statement in the data structure.
The function is invoked with each statement as its only argument and
always returns :ok. It is useful for executing side effects on the data.
Examples
RDF.Data.each(graph, &IO.inspect/1)
# prints each statement
# => :ok
@spec empty?(RDF.Data.Source.t()) :: boolean()
Returns true if the given RDF data structure is empty.
Examples
iex> RDF.Data.empty?(RDF.graph())
true
iex> RDF.Data.empty?(RDF.graph([{EX.S, EX.p, EX.O}]))
false
@spec equal?(RDF.Data.Source.t(), RDF.Data.Source.t()) :: boolean()
Checks equality of two data structures.
Supports cross-structure comparisons with special rules:
- description equals graph if graph contains only that description
- graph equals dataset if dataset contains only that graph
- otherwise compares statement sets
Examples
iex> desc1 = EX.S |> EX.p(EX.O)
iex> desc2 = EX.S |> EX.p(EX.O)
iex> RDF.Data.equal?(desc1, desc2)
true
iex> desc = EX.S |> EX.p(EX.O)
iex> graph = RDF.graph([{EX.S, EX.p(), EX.O}])
iex> RDF.Data.equal?(desc, graph)
true
iex> graph = RDF.graph([{EX.S, EX.p(), EX.O}])
iex> dataset = RDF.dataset([{EX.S, EX.p(), EX.O, nil}])
iex> RDF.Data.equal?(graph, dataset)
true
@spec filter(RDF.Data.Source.t(), (RDF.Statement.t() -> boolean())) :: RDF.Data.Source.t()
Filters statements in the data structure based on a predicate function.
Returns a new data structure of the same type containing only the statements for which the predicate function returns a truthy value.
Examples
iex> graph = RDF.graph([{EX.S1, EX.p1, EX.O1}, {EX.S2, EX.p2, EX.O2}])
iex> RDF.Data.filter(graph, fn {_s, p, _o} -> p == EX.p1 end)
RDF.graph([{EX.S1, EX.p1, EX.O1}])
iex> dataset = RDF.dataset([{EX.S, EX.p1, EX.O, EX.G}, {EX.S, EX.p2, EX.O, nil}])
iex> RDF.Data.filter(dataset, fn {_s, p, _o, _g} -> p == EX.p1 end)
RDF.dataset([{EX.S, EX.p1, EX.O, EX.G}])
@spec graph(RDF.Data.Source.t(), RDF.Resource.coercible() | nil) :: RDF.Data.Source.t()
Returns a specific graph from the RDF data structure.
If the graph doesn't exist, an empty graph is returned.
Use graph/3 to provide a custom default value.
Examples
iex> dataset = RDF.dataset([{EX.S, EX.p, EX.O, EX.Graph1}])
iex> RDF.Data.graph(dataset, EX.Graph1)
RDF.graph({EX.S, EX.p, EX.O}, name: EX.Graph1)
iex> dataset = RDF.dataset([{EX.S, EX.p, EX.O, EX.Graph1}])
iex> RDF.Data.graph(dataset, EX.NonExistent)
RDF.graph(name: EX.NonExistent)
@spec graph(RDF.Data.Source.t(), RDF.Resource.coercible() | nil, default) :: RDF.Data.Source.t() | default when default: term()
Returns a specific graph from the RDF data structure, or a default value if not found.
Examples
iex> dataset = RDF.dataset([{EX.S, EX.p, EX.O, EX.Graph1}])
iex> RDF.Data.graph(dataset, EX.Graph1, nil)
RDF.graph({EX.S, EX.p, EX.O}, name: EX.Graph1)
iex> dataset = RDF.dataset([{EX.S, EX.p, EX.O, EX.Graph1}])
iex> RDF.Data.graph(dataset, EX.NonExistent, nil)
nil
iex> dataset = RDF.dataset([{EX.S, EX.p, EX.O, EX.Graph1}])
iex> RDF.Data.graph(dataset, EX.NonExistent, :not_found)
:not_found
@spec graph_count(RDF.Data.Source.t()) :: non_neg_integer()
Returns the count of graphs in the RDF data structure.
Depending on the structure type, the count represents:
:description: Always 1 (implicit unnamed graph):graph: Always 1:dataset: Number of graphs (including default if present)
Examples
iex> desc = EX.S |> EX.p(EX.O)
iex> RDF.Data.graph_count(desc)
1
iex> graph = RDF.graph([{EX.S1, EX.p, EX.O1}])
iex> RDF.Data.graph_count(graph)
1
iex> dataset = RDF.dataset([
...> {EX.S1, EX.p, EX.O1, nil},
...> {EX.S2, EX.p, EX.O2, EX.Graph}
...> ])
iex> RDF.Data.graph_count(dataset)
2
iex> RDF.Data.graph_count(RDF.dataset())
0
@spec graph_names(RDF.Data.Source.t()) :: [RDF.IRI.t() | nil]
Returns all graph names in the data structure.
Behavior by structure type:
:description: Always returns[nil](implicit unnamed graph):graph: Returns[name]where name is the graph's name (could benil):dataset: Returns all graph names
Examples
iex> desc = EX.S |> EX.p(EX.O)
iex> RDF.Data.graph_names(desc)
[nil]
iex> graph = RDF.Graph.new([{EX.S, EX.p, EX.O}], name: EX.Graph1)
iex> RDF.Data.graph_names(graph)
[~I<http://example.com/Graph1>]
iex> dataset = RDF.Dataset.new([{EX.S, EX.p, EX.O, EX.G1}, {EX.S2, EX.p, EX.O2, nil}])
iex> RDF.Data.graph_names(dataset)
[nil, ~I<http://example.com/G1>]
@spec graphs(RDF.Data.Source.t()) :: [RDF.Data.Source.t()]
Returns all graphs in the data structure.
Behavior by structure type:
:description: returns a single graph containing the description:graph: returns a list containing the graph itself:dataset: returns all graphs (including the default graph if present)
Examples
iex> description = EX.S |> EX.p(EX.O)
iex> RDF.Data.graphs(description)
[RDF.graph(description)]
iex> graph = RDF.graph([{EX.S, EX.p, EX.O}])
iex> RDF.Data.graphs(graph)
[graph]
iex> dataset = RDF.dataset([{EX.S1, EX.p, EX.O1, nil}, {EX.S2, EX.p, EX.O2, EX.graph1}])
iex> RDF.Data.graphs(dataset)
[RDF.graph([{EX.S1, EX.p, EX.O1}]), RDF.graph([{EX.S2, EX.p, EX.O2}], name: EX.graph1)]
@spec include?( data :: RDF.Data.Source.t(), statements :: RDF.Statement.t() | [RDF.Statement.t()] | RDF.Data.Source.t() ) :: boolean()
Checks if data includes the given statements.
Returns true if all given statements are present in the data structure.
The statements parameter can be:
- A single triple
{s, p, o}or quad{s, p, o, g} - A list of triples or quads
- Another structure implementing
RDF.Data.Source
For datasets, triple patterns (without graph) are matched against all
graphs. Use a quad {s, p, o, graph_name} to check a specific graph (including
nil for the default graph).
Examples
iex> graph = RDF.Graph.new([{EX.S, EX.p, EX.O}])
iex> RDF.Data.include?(graph, {EX.S, EX.p, EX.O})
true
iex> graph = RDF.Graph.new([{EX.S, EX.p, EX.O}])
iex> RDF.Data.include?(graph, [{EX.S, EX.p, EX.O}])
true
iex> graph = RDF.Graph.new([{EX.S, EX.p, EX.O}])
iex> desc = EX.S |> EX.p(EX.O)
iex> RDF.Data.include?(graph, desc)
true
iex> dataset = RDF.Dataset.new([
...> {EX.S1, EX.p, EX.O1, nil},
...> {EX.S2, EX.p, EX.O2, EX.Graph}
...> ])
iex> RDF.Data.include?(dataset, {EX.S1, EX.p, EX.O1})
true
iex> RDF.Data.include?(dataset, {EX.S2, EX.p, EX.O2})
true
iex> RDF.Data.include?(dataset, {EX.S2, EX.p, EX.O2, nil})
false
iex> RDF.Data.include?(dataset, {EX.S2, EX.p, EX.O2, EX.Graph})
true
@spec map(RDF.Data.Source.t(), (RDF.Statement.t() -> RDF.Statement.t() | [RDF.Statement.t()] | nil)) :: RDF.Data.Source.t()
Maps a transformation function over all statements in the data structure.
The given fun function can return:
- a statement tuple (triple or quad) - included in the result
- a list of statements - flattened and included in the result
nil- excluded from the result
Structural promotion
The result structure type depends on the mapped statements:
- stays the same type when all mapped statements fit the original structure
- promotes to a graph structure when statements have different subjects
- promotes to a dataset structure when statements have different graph names
Examples
iex> RDF.Data.map(EX.S |> EX.p(EX.O), fn {s, p, _o} -> {s, p, EX.New} end)
EX.S |> EX.p(EX.New)
iex> RDF.Data.map(RDF.graph({EX.S, EX.p, EX.O}), fn {s, p, _o} -> {s, p, EX.New} end)
RDF.graph({EX.S, EX.p, EX.New})Description upgrades to graph when mapped statements have different subjects:
iex> desc = EX.S |> EX.p(EX.O1) |> EX.p(EX.O2)
iex> RDF.Data.map(desc, fn {_s, p, o} -> {o, p, EX.S} end)
RDF.graph([{EX.O1, EX.p, EX.S}, {EX.O2, EX.p, EX.S}])Graph upgrades to dataset when mapped statements have different graph names:
iex> graph = RDF.graph([{EX.S, EX.p, EX.O1}, {EX.S, EX.p, EX.O2}])
iex> RDF.Data.map(graph, fn {s, p, o} -> {s, p, o, o} end)
RDF.dataset([{EX.S, EX.p, EX.O1, EX.O1}, {EX.S, EX.p, EX.O2, EX.O2}])
@spec map_reduce(RDF.Data.Source.t(), acc, (RDF.Statement.t(), acc -> {mapped, acc})) :: {RDF.Data.Source.t(), acc} when acc: term(), mapped: RDF.Statement.t() | [RDF.Statement.t()] | nil
Transforms statements and accumulates a value in a single pass.
Combines the functionality of map/2 with an accumulator, similar to
Enum.map_reduce/3. For each statement, the function receives the statement
and the current accumulator, and returns a tuple with the mapped result and
the new accumulator.
The mapped result can be:
- a statement (triple or quad) - replaces the original statement
nil- filters out the statement- a list of statements - expands to multiple statements
Like map/2, structural promotion occurs based on the mapped results.
Examples
iex> graph = RDF.graph([{EX.S1, EX.p1, EX.O1}, {EX.S2, EX.p2, EX.O2}])
iex> RDF.Data.map_reduce(graph, 0, fn {s, p, _o}, count ->
...> {{s, p, EX.New}, count + 1}
...> end)
{RDF.graph([{EX.S1, EX.p1, EX.New}, {EX.S2, EX.p2, EX.New}]), 2}
@spec merge([RDF.Data.Source.t() | RDF.Statement.t()]) :: RDF.Data.Source.t()
Merges a list of data structures and/or statements into a single structure.
Examples
iex> graph = RDF.graph({EX.S1, EX.p1, EX.O1})
iex> RDF.Data.merge([graph, {EX.S2, EX.p2, EX.O2}, EX.S3 |> EX.p3(EX.O3)])
RDF.graph([{EX.S1, EX.p1, EX.O1}, {EX.S2, EX.p2, EX.O2}, {EX.S3, EX.p3, EX.O3}])
iex> RDF.Data.merge([])
RDF.graph()
@spec merge( RDF.Data.Source.t(), RDF.Data.Source.t() | RDF.Statement.t() | [RDF.Data.Source.t() | RDF.Statement.t()] ) :: RDF.Data.Source.t()
Merges two data structures with automatic structural promotion.
Rules:
- Description + Description with same subject → Description
- Description + Description with different subjects → Graph
- Graph + Graph with same name → Graph
- Graph + Graph with different names → Dataset
- Otherwise, promotes to the most complex structure required
Examples
iex> desc1 = EX.S |> EX.p1(EX.O1)
iex> desc2 = EX.S |> EX.p2(EX.O2)
iex> RDF.Data.merge(desc1, desc2)
EX.S |> EX.p1(EX.O1) |> EX.p2(EX.O2)
iex> graph1 = RDF.graph([{EX.S1, EX.p, EX.O}], name: EX.G1)
iex> graph2 = RDF.graph([{EX.S2, EX.p, EX.O}], name: EX.G2)
iex> RDF.Data.merge(graph1, graph2)
RDF.dataset([{EX.S1, EX.p, EX.O, EX.G1}, {EX.S2, EX.p, EX.O, EX.G2}])
@spec object_resources(RDF.Data.Source.t()) :: [RDF.Resource.t()]
Returns all unique resource objects in the data structure.
Resource objects are IRIs and blank nodes, excluding literals.
For all object terms including literals, use objects/1.
Examples
iex> graph = RDF.Graph.new([{EX.S, EX.p, EX.O1}, {EX.S, EX.p2, "literal"}])
iex> RDF.Data.object_resources(graph)
[~I<http://example.com/O1>]
@spec objects(RDF.Data.Source.t()) :: [RDF.Term.t()]
Returns all unique object terms in the data structure.
Object terms include all RDF terms: IRIs, blank nodes, and literals.
Examples
iex> graph = RDF.Graph.new([{EX.S, EX.p, EX.O1}, {EX.S, EX.p2, "literal"}])
iex> RDF.Data.objects(graph)
[~L"literal", ~I<http://example.com/O1>]
@spec objects(RDF.Data.Source.t(), (RDF.Term.t() -> boolean()) | nil) :: [ RDF.Term.t() ]
Returns all unique object terms in the data structure matching the filter function.
Examples
iex> graph = RDF.graph([{EX.S, EX.p, EX.O}, {EX.S, EX.p2, "literal"}])
iex> RDF.Data.objects(graph, &RDF.resource?/1)
[RDF.iri(EX.O)]
@spec pop(RDF.Data.Source.t()) :: {RDF.Statement.t() | nil, RDF.Data.Source.t()}
Removes and returns one statement from the RDF data structure.
Returns a tuple {statement, remaining_data} where statement is a triple or quad,
and remaining_data is the data structure without that statement. For empty data
structures, returns {nil, data}.
The specific statement returned is implementation-dependent and should not be relied upon for ordering.
Examples
iex> graph = RDF.graph([{EX.S, EX.p, EX.O}])
iex> {triple, remaining} = RDF.Data.pop(graph)
iex> triple
{~I<http://example.com/S>, EX.p(), ~I<http://example.com/O>}
iex> RDF.Graph.empty?(remaining)
true
iex> RDF.Data.pop(RDF.graph())
{nil, RDF.graph()}
@spec predicate_count(RDF.Data.Source.t()) :: non_neg_integer()
Returns the count of unique predicates in the data structure.
Examples
iex> desc = EX.S |> EX.p(EX.O1) |> EX.q(EX.O2)
iex> RDF.Data.predicate_count(desc)
2
iex> graph = RDF.Graph.new([{EX.S1, EX.p, EX.O1}, {EX.S2, EX.p, EX.O2}, {EX.S3, EX.q, EX.O3}])
iex> RDF.Data.predicate_count(graph)
2
@spec predicates(RDF.Data.Source.t()) :: [RDF.IRI.t()]
Returns all unique predicates in the data structure.
Examples
iex> graph = RDF.Graph.new([{EX.S, EX.p1, EX.O}, {EX.S, EX.p2, EX.O}])
iex> RDF.Data.predicates(graph)
[~I<http://example.com/p1>, ~I<http://example.com/p2>]
@spec predicates(RDF.Data.Source.t(), (RDF.IRI.t() -> boolean()) | nil) :: [ RDF.IRI.t() ]
Returns all unique predicates in the data structure matching the filter function.
Examples
iex> graph = RDF.graph([{EX.S, EX.p1, EX.O}, {EX.S, EX.p2, EX.O}])
iex> RDF.Data.predicates(graph, &(&1 == EX.p1()))
[EX.p1()]
@spec quads(RDF.Data.Source.t()) :: [RDF.Quad.t()]
Returns all statements as quads.
Converts all statements to quad format {subject, predicate, object, graph_name}.
For descriptions and graphs, adds the graph name (or nil for default graph).
Examples
iex> graph = RDF.graph([{EX.S, EX.p, EX.O}])
iex> RDF.Data.quads(graph)
[{~I<http://example.com/S>, EX.p(), ~I<http://example.com/O>, nil}]
iex> named_graph = RDF.graph([{EX.S, EX.p, EX.O}], name: EX.G)
iex> RDF.Data.quads(named_graph)
[{~I<http://example.com/S>, EX.p(), ~I<http://example.com/O>, ~I<http://example.com/G>}]
@spec reduce(RDF.Data.Source.t(), (RDF.Statement.t(), acc -> acc)) :: acc when acc: term()
Reduces the RDF data structure using the given function without an initial accumulator.
The first statement becomes the initial accumulator.
Raises Enum.EmptyError if the data structure is empty.
@spec reduce(RDF.Data.Source.t(), acc, (RDF.Statement.t(), acc -> acc)) :: acc when acc: term()
Reduces the RDF data structure using the given function.
Similar to Enum.reduce/3, applies fun to each statement in the data structure
to produce a single result. This is the user-facing function that hides the
complexity of the protocol's tagged tuple system.
Examples
iex> graph = RDF.graph([{EX.S1, EX.p, EX.O1}, {EX.S2, EX.p, EX.O2}])
iex> RDF.Data.reduce(graph, 0, fn {_s, _p, _o}, acc -> acc + 1 end)
2
@spec reduce_while( RDF.Data.Source.t(), acc, (RDF.Statement.t(), acc -> {:cont, acc} | {:halt, acc}) ) :: acc when acc: term()
Reduces the RDF data structure using the given function with early termination support.
Similar to Enum.reduce_while/3, applies fun to each statement in the data structure
with the ability to halt iteration early. The function must return:
{:cont, acc}to continue iteration with the new accumulator{:halt, acc}to stop iteration and return the accumulator
Examples
iex> graph = RDF.graph([{EX.S1, EX.p, EX.O1}, {EX.S2, EX.p, EX.O2}, {EX.S3, EX.p, EX.O3}])
iex> RDF.Data.reduce_while(graph, 0, fn _stmt, acc -> {:cont, acc + 1} end)
3
iex> graph = RDF.graph([{EX.S1, EX.p, EX.O1}, {EX.target, EX.p, EX.O2}])
iex> RDF.Data.reduce_while(graph, nil, fn {s, _p, _o}, _acc ->
...> if s == ~I<http://example.com/target> do
...> {:halt, s}
...> else
...> {:cont, nil}
...> end
...> end)
~I<http://example.com/target>
@spec reject(RDF.Data.Source.t(), (RDF.Statement.t() -> boolean())) :: RDF.Data.Source.t()
Rejects statements in the data structure based on a predicate function.
Returns a new data structure of the same type containing only the statements for which the predicate function returns a falsy value.
This is the complement of filter/2.
Examples
iex> graph = RDF.graph([{EX.S1, EX.p1, EX.O1}, {EX.S2, EX.p2, EX.O2}])
iex> RDF.Data.reject(graph, fn {_s, p, _o} -> p == EX.p1 end)
RDF.graph([{EX.S2, EX.p2, EX.O2}])
iex> dataset = RDF.dataset([{EX.S, EX.p1, EX.O, EX.G}, {EX.S, EX.p2, EX.O, nil}])
iex> RDF.Data.reject(dataset, fn {_s, p, _o, _g} -> p == EX.p1 end)
RDF.dataset([{EX.S, EX.p2, EX.O}])
@spec resources( RDF.Data.Source.t(), keyword() | (RDF.Resource.t() -> boolean()) | (RDF.Resource.t(), atom() -> boolean()) ) :: [RDF.Resource.t()]
Returns all unique resources (non-literal terms) in the data structure.
The second argument can be either a keyword list of options or a filter function.
Options
:predicates- whentrue, includes predicates in the result (default:false):filter- a filter function (see below)
Filter function
The filter function can be:
- a 1-arity function receiving only the term
- a 2-arity function receiving
(term, position)where position is:subject,:predicate, or:object
Examples
iex> graph = RDF.Graph.new([{EX.S, EX.p, EX.O}, {EX.S, EX.p2, "literal"}])
iex> RDF.Data.resources(graph)
[~I<http://example.com/O>, ~I<http://example.com/S>]
iex> graph = RDF.Graph.new([{EX.S, EX.p, EX.O}])
iex> RDF.Data.resources(graph, predicates: true)
[~I<http://example.com/O>, ~I<http://example.com/S>, ~I<http://example.com/p>]
iex> graph = RDF.graph([{EX.S, EX.p, EX.O}, {RDF.bnode(), EX.p2, EX.O2}])
iex> RDF.Data.resources(graph, &RDF.iri?/1) |> MapSet.new()
MapSet.new([RDF.iri(EX.S), RDF.iri(EX.O), RDF.iri(EX.O2)])
iex> graph = RDF.graph([{EX.S, EX.p, EX.O}])
iex> RDF.Data.resources(graph, fn _term, pos -> pos == :subject end)
[RDF.iri(EX.S)]
@spec statement_count(RDF.Data.Source.t()) :: non_neg_integer()
Returns the count of statements in the RDF data structure.
Examples
iex> graph = RDF.graph([{EX.S1, EX.p, EX.O1}, {EX.S2, EX.p, EX.O2}])
iex> RDF.Data.statement_count(graph)
2
iex> RDF.Data.statement_count(RDF.dataset())
0
@spec statements(RDF.Data.Source.t()) :: [RDF.Statement.t()]
Returns all statements in the data structure.
Extracts all statements as a list. The format depends on the structure type:
:descriptionand:graph: Returns triples{subject, predicate, object}:dataset: Returns quads{subject, predicate, object, graph_name}
Examples
iex> graph = RDF.graph([{EX.S, EX.p, EX.O}])
iex> RDF.Data.statements(graph)
[{~I<http://example.com/S>, EX.p(), ~I<http://example.com/O>}]
iex> dataset = RDF.dataset([{EX.S, EX.p, EX.O, EX.G}])
iex> RDF.Data.statements(dataset)
[{~I<http://example.com/S>, EX.p(), ~I<http://example.com/O>, ~I<http://example.com/G>}]
@spec subject_count(RDF.Data.Source.t()) :: non_neg_integer()
Returns the count of unique subjects in the RDF data structure.
Examples
iex> graph = RDF.graph([{EX.S1, EX.p, EX.O1}, {EX.S2, EX.p, EX.O2}])
iex> RDF.Data.subject_count(graph)
2
iex> RDF.Data.subject_count(EX.S |> EX.p(EX.O))
1
iex> RDF.Data.subject_count(RDF.graph())
0
@spec subjects(RDF.Data.Source.t()) :: [RDF.Resource.t()]
Returns all unique subjects in the data structure.
Examples
iex> graph = RDF.Graph.new([{EX.S1, EX.p, EX.O}, {EX.S2, EX.p, EX.O}])
iex> RDF.Data.subjects(graph)
[~I<http://example.com/S1>, ~I<http://example.com/S2>]
@spec subjects(RDF.Data.Source.t(), (RDF.Resource.t() -> boolean()) | nil) :: [ RDF.Resource.t() ]
Returns all unique subjects in the data structure matching the filter function.
Examples
iex> graph = RDF.graph([{EX.S1, EX.p, EX.O}, {RDF.bnode(:b), EX.p, EX.O}])
iex> RDF.Data.subjects(graph, &RDF.iri?/1)
[RDF.iri(EX.S1)]
@spec take(RDF.Data.Source.t(), integer()) :: RDF.Data.Source.t()
Takes the first amount statements from the RDF data structure.
Returns a new data structure of the same type containing at most amount statements.
The order of statements is implementation-dependent and should not be relied upon.
For negative amounts, returns an empty data structure.
Examples
iex> graph = RDF.graph([{EX.S1, EX.p, EX.O1}, {EX.S2, EX.p, EX.O2}, {EX.S3, EX.p, EX.O3}])
iex> RDF.Data.statement_count(RDF.Data.take(graph, 2))
2
iex> RDF.Data.take(RDF.graph(), 5)
RDF.graph()
@spec to_dataset( RDF.Data.Source.t(), keyword() ) :: RDF.Dataset.t() | RDF.Data.Source.t()
Converts the RDF data structure to a dataset.
If the data is already a dataset and no options are provided, returns it unchanged. For graphs, the graph is embedded preserving its name (named or default graph).
Options
:native- Forces conversion to nativeRDF.Dataset(default:false)
Examples
iex> desc = EX.S |> EX.p(EX.O)
iex> RDF.Data.to_dataset(desc)
RDF.dataset({EX.S, EX.p(), EX.O})
iex> graph = RDF.graph([{EX.S, EX.p, EX.O}], name: EX.G)
iex> RDF.Data.to_dataset(graph)
RDF.dataset({EX.S, EX.p(), EX.O, EX.G})
iex> dataset = RDF.dataset([{EX.S, EX.p, EX.O, EX.G}])
iex> RDF.Data.to_dataset(dataset)
dataset
@spec to_graph( RDF.Data.Source.t(), keyword() ) :: RDF.Graph.t() | RDF.Data.Source.t()
Converts the RDF data structure to a graph.
If the data is already a graph and no options are provided, returns it unchanged. For datasets, all graphs are merged into a single graph (graph names are lost).
Options
:native- Forces conversion to nativeRDF.Graph(default:false)
Examples
iex> desc = EX.S |> EX.p(EX.O)
iex> RDF.Data.to_graph(desc)
RDF.graph({EX.S, EX.p(), EX.O})
iex> graph = RDF.graph([{EX.S, EX.p, EX.O}], name: EX.G)
iex> RDF.Data.to_graph(graph)
graph
iex> dataset = RDF.dataset([{EX.S1, EX.p, EX.O1, EX.G1}, {EX.S2, EX.p, EX.O2, EX.G2}])
iex> RDF.Data.to_graph(dataset)
RDF.graph([{EX.S1, EX.p, EX.O1}, {EX.S2, EX.p, EX.O2}])
@spec triples(RDF.Data.Source.t()) :: [RDF.Triple.t()]
Returns all statements as triples.
Converts all statements to triple format {subject, predicate, object}.
For Datasets, this drops the graph component from quads.
Examples
iex> graph = RDF.graph([{EX.S, EX.p, EX.O}])
iex> RDF.Data.triples(graph)
[{~I<http://example.com/S>, EX.p(), ~I<http://example.com/O>}]
iex> dataset = RDF.dataset([{EX.S, EX.p, EX.O, EX.G}])
iex> RDF.Data.triples(dataset)
[{~I<http://example.com/S>, EX.p(), ~I<http://example.com/O>}]