Current section
Files
Jump to
Current section
Files
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