PtcRunner.Lisp.Format (PtcRunner v0.9.0)

Copy Markdown View Source

Format PTC-Lisp values for human/LLM display.

Handles special Lisp types that should not expose internal implementation:

  • Closures: {:closure, params, body, env, history, metadata}#fn[x y]
  • Builtins: {:normal, fun} etc. → #<builtin>

Works recursively, so closures nested in maps/lists are also formatted.

Examples

iex> PtcRunner.Lisp.Format.to_string({:closure, [{:var, :x}], nil, %{}, [], %{}})
"#fn[x]"

iex> PtcRunner.Lisp.Format.to_string({:normal, &Enum.map/2})
"#<builtin>"

iex> PtcRunner.Lisp.Format.to_string(%{a: 1})
"%{a: 1}"

Summary

Functions

Format a Lisp value as Clojure syntax for LLM feedback.

Format a Lisp value as a string for display.

Functions

to_clojure(value, opts \\ [])

@spec to_clojure(
  term(),
  keyword()
) :: {String.t(), boolean()}

Format a Lisp value as Clojure syntax for LLM feedback.

Produces Clojure-style output that matches the syntax the LLM writes:

  • Maps: {:key value} instead of %{key: value}
  • Lists: [1 2 3] (space-separated) instead of [1, 2, 3]
  • Keywords: :foo (same as Clojure)
  • Strings/numbers/booleans: standard literals

Returns {formatted_string, truncated?} tuple.

Options

  • :limit - Maximum items to show in collections (default: :infinity)
  • :printable_limit - Maximum string bytes to show (default: :infinity)

Examples

iex> PtcRunner.Lisp.Format.to_clojure(42)
{"42", false}

iex> PtcRunner.Lisp.Format.to_clojure([1, 2, 3])
{"[1 2 3]", false}

iex> PtcRunner.Lisp.Format.to_clojure(%{id: 101, count: 45})
{"{:count 45 :id 101}", false}

iex> PtcRunner.Lisp.Format.to_clojure(%{"name" => "Alice", "age" => 30})
{~s({"age" 30 "name" "Alice"}), false}

iex> PtcRunner.Lisp.Format.to_clojure({:closure, [{:var, :x}], nil, %{}, [], %{}})
{"#fn[x]", false}

iex> PtcRunner.Lisp.Format.to_clojure({:var, :x})
{"#'x", false}

iex> PtcRunner.Lisp.Format.to_clojure(nil)
{"nil", false}

iex> PtcRunner.Lisp.Format.to_clojure(:keyword)
{":keyword", false}

iex> PtcRunner.Lisp.Format.to_clojure([%{a: 1}, %{b: 2}])
{"[{:a 1} {:b 2}]", false}

iex> PtcRunner.Lisp.Format.to_clojure([1, 2, 3, 4, 5], limit: 2)
{"[1 2 ...] (5 items, showing first 2)", true}

iex> PtcRunner.Lisp.Format.to_clojure("very long string here", printable_limit: 10)
{~s("very long ..."), true}

iex> {str, _} = PtcRunner.Lisp.Format.to_clojure(%{title: "Hello", _body: "secret"})
iex> str
~s[{:title "Hello"}]

iex> {str, _} = PtcRunner.Lisp.Format.to_clojure(%{title: "Hello", _body: "secret"}, filter_hidden: false)
iex> str
~s[{:_body "secret" :title "Hello"}]

to_string(value, opts \\ [])

@spec to_string(
  term(),
  keyword()
) :: String.t()

Format a Lisp value as a string for display.

Options

All options are passed through to Kernel.inspect/2 for regular values:

  • :pretty - Use pretty-printing
  • :limit - Maximum items to show in collections
  • :width - Target width for pretty printing
  • :printable_limit - Maximum string bytes to show

Examples

iex> PtcRunner.Lisp.Format.to_string(42)
"42"

iex> PtcRunner.Lisp.Format.to_string({:closure, [{:var, :x}, {:var, :y}], nil, %{}, [], %{}})
"#fn[x y]"

iex> PtcRunner.Lisp.Format.to_string({:var, :my_var})
"#'my_var"

iex> PtcRunner.Lisp.Format.to_string([1, 2, 3], limit: 2)
"[1, 2, ...]"

iex> PtcRunner.Lisp.Format.to_string(%{f: {:closure, [{:var, :x}], nil, %{}, [], %{}}})
"%{f: #fn[x]}"