Packages

Guesswork is a logic programming library for Elixir. It is heavily inspired by Prolog, but attempts to use idiomatic Elixir when expressing problems and their solutions.

Current section

Files

Jump to
guesswork lib guesswork answer result.ex
Raw

lib/guesswork/answer/result.ex

defmodule Guesswork.Answer.Result do
@moduledoc """
A module for evaluating and displaying query results.
"""
defstruct answer_sets: %{}
alias Guesswork.Query
alias Guesswork.Answer
alias Guesswork.Ast.Term
alias Guesswork.Telemetry.EventHandler
@type value() ::
{:bound, Term.entity()}
| {:not, [Term.entity()]}
| {:constraints, [String.t()]}
@type t() :: %__MODULE__{answer_sets: [%{String.t() => value()}]}
@event_prefix EventHandler.resolve_span_prefix()
@doc """
Takes a query and attempts to resolve `n` answers from it.
"""
@spec run(Query.t(), integer()) :: t()
def run(%Query{computation: computation, id: id}, n \\ 1) do
metadata = %{query_id: id, run_id: UUID.uuid4(), n: n}
answers =
:telemetry.span(@event_prefix, metadata, fn ->
result = Enum.take(computation, n)
{result, metadata}
end)
%__MODULE__{answer_sets: Enum.map(answers, &Answer.flatten/1)}
end
@doc """
Returns the event prefix used by `run/2` to create a telemetry span.
"""
@spec event_prefix() :: [atom()]
def event_prefix(), do: @event_prefix
@doc """
Takes a value and produces a readable string.
"""
@spec value_to_string(value()) :: String.t()
def value_to_string({:bound, value}), do: "#{inspect(value)}"
def value_to_string({:not, values}), do: "not #{inspect(values)}"
def value_to_string({:constraints, values}), do: Enum.join(values, ", ")
defimpl Kino.Render do
alias Guesswork.Answer.Result
def to_livebook(%Guesswork.Answer.Result{answer_sets: answer_sets}) do
answer_sets
|> Enum.map(&Map.new(&1, fn {key, value} -> {key, Result.value_to_string(value)} end))
|> Kino.DataTable.new()
|> Kino.Render.to_livebook()
end
end
end