View Source Guesswork.Ast.Fact (Guesswork v0.8.0)

A fact is just a relationship (string) and some entities (concrete or non-concrete) and states that the relationship hold for those values in that order.

Summary

Functions

Extracts the relationship name and arity.

Takes two facts and attempt to 'match' them by ensuring that their relationships match, all concrete terms match, and then binding any variables in the first fact to values in the opposite entity. Returns nil if the match fails, an answer set if it succeeds.

Attempts to substitute the values in the second fact for any variables in the first. Returns nil if the relation doesn't match, any concrete entities don't match, or if the second fact attempts to substitute a variable for a concrete value.

Types

arg()

metadata()

@type metadata() :: {String.t(), integer()}

t()

@type t() :: %Guesswork.Ast.Fact{
  args: [arg()],
  arity: integer(),
  relationship: atom()
}

Functions

get_metadata(fact)

@spec get_metadata(t()) :: metadata()

Extracts the relationship name and arity.

match(fact1, fact2, query_id)

@spec match(t(), t(), String.t()) :: nil | Guesswork.Answer.t()

Takes two facts and attempt to 'match' them by ensuring that their relationships match, all concrete terms match, and then binding any variables in the first fact to values in the opposite entity. Returns nil if the match fails, an answer set if it succeeds.

Note that the same concrete fact matched on itself will result in an empty answer set and that variables match variables.

Examples

iex> f1 = Guesswork.Ast.Fact.new(:thing, [:a, :b, :c])
...> f2 = Guesswork.Ast.Fact.new(:thing, [:a, :b, :c])
...> Guesswork.Ast.Fact.match(f1, f2, "test")
Guesswork.Answer.new("test")
iex> f1 = Guesswork.Ast.Fact.new(:thing, [:a, :b, :c])
...> f2 = Guesswork.Ast.Fact.new(:thing, [:a, :b, :d])
...> Guesswork.Ast.Fact.match(f1, f2, "test")
nil
iex> var1 = Guesswork.Ast.Variable.new("x")
...> var2 = Guesswork.Ast.Variable.new("y")
...> f1 = Guesswork.Ast.Fact.new(:thing, [var1, :b, :c])
...> f2 = Guesswork.Ast.Fact.new(:thing, [:a, :b, var2])
...> Guesswork.Ast.Fact.match(f1, f2, "test")
%Guesswork.Answer{
  query_id: "test",
  bindings: %{
    "x" => Guesswork.Answer.Binding.new(:a, false)
  }
}
iex> var = Guesswork.Ast.Variable.new("x")
...> f1 = Guesswork.Ast.Fact.new(:thing, [var, :b, var])
...> f2 = Guesswork.Ast.Fact.new(:thing, [:a, :b, :c])
...> Guesswork.Ast.Fact.match(f1, f2, "test")
nil
iex> var = Guesswork.Ast.Variable.new("x")
...> f1 = Guesswork.Ast.Fact.new(:thing, [:a, :b, var])
...> f2 = Guesswork.Ast.Fact.new(:thing, [:a, var, var])
...> Guesswork.Ast.Fact.match(f1, f2, "test")
%Guesswork.Answer{
  query_id: "test",
  bindings: %{
    "x" => Guesswork.Answer.Binding.new(:b, false)
  }
}

new(relationship, args)

substitute(fact1, fact2)

@spec substitute(t(), t()) :: Guesswork.Ast.Statement.env() | nil

Attempts to substitute the values in the second fact for any variables in the first. Returns nil if the relation doesn't match, any concrete entities don't match, or if the second fact attempts to substitute a variable for a concrete value.

Example

iex> f1 = Guesswork.Ast.Fact.new(:thing, [:a, :b, :c])
...> f2 = Guesswork.Ast.Fact.new(:other, [:a, :b, :c])
...> Guesswork.Ast.Fact.substitute(f1, f2)
nil
iex> f1 = Guesswork.Ast.Fact.new(:thing, [:a, :b, :c])
...> f2 = Guesswork.Ast.Fact.new(:thing, [:a, :b, :c])
...> Guesswork.Ast.Fact.substitute(f1, f2)
%{}
iex> var = Guesswork.Ast.Variable.new("x")
...> f1 = Guesswork.Ast.Fact.new(:thing, [:a, :b, :c])
...> f2 = Guesswork.Ast.Fact.new(:thing, [:a, var, :c])
...> Guesswork.Ast.Fact.substitute(f1, f2)
nil
iex> var1 = Guesswork.Ast.Variable.new("x")
...> var2 = Guesswork.Ast.Variable.new("y")
...> f1 = Guesswork.Ast.Fact.new(:thing, [:a, var1, var2])
...> f2 = Guesswork.Ast.Fact.new(:thing, [:a, :b, :c])
...> Guesswork.Ast.Fact.substitute(f1, f2)
%{var1 => :b, var2 => :c}
iex> var1 = Guesswork.Ast.Variable.new("x")
...> var2 = Guesswork.Ast.Variable.new("y")
...> f1 = Guesswork.Ast.Fact.new(:thing, [:a, var1, :c])
...> f2 = Guesswork.Ast.Fact.new(:thing, [:a, var2, :c])
...> Guesswork.Ast.Fact.substitute(f1, f2)
%{var1 => var2}
iex> var1 = Guesswork.Ast.Variable.new("x")
...> var2 = Guesswork.Ast.Variable.new("y")
...> f1 = Guesswork.Ast.Fact.new(:thing, [:a, var1, var2])
...> f2 = Guesswork.Ast.Fact.new(:thing, [:a, :b, :b])
...> Guesswork.Ast.Fact.substitute(f1, f2)
%{var1 => :b, var2 => :b}