Skip to content

Instantly share code, notes, and snippets.

@hauleth
Created November 28, 2025 17:45
Show Gist options
  • Select an option

  • Save hauleth/aaec6500dae1a40f91f610b6141ead30 to your computer and use it in GitHub Desktop.

Select an option

Save hauleth/aaec6500dae1a40f91f610b6141ead30 to your computer and use it in GitHub Desktop.
defmodule Foo do
defmacro fn_rec(do: body) do
{name, argc, body} =
body
|> Enum.map(fn
{:'->', e1, [[{:when, e2, [{name, _, args}, guard]}], body]} ->
{name, length(args), {:'->', e1, [[{:when, e2, args ++ [guard]}], body]}}
{:'->', e1, [[{name, _, args}], body]} ->
{name, length(args), {:'->', e1, [args, body]}}
end)
|> Enum.reduce(fn {name, argc, body}, {name, argc, acc} ->
{name, argc, List.wrap(acc) ++ [body]}
end)
args = Macro.generate_arguments(argc, __CALLER__.module)
func = {:fn, [], body}
name = {name, [], Elixir}
quote do
tmp =
fn f ->
var!(unquote(name)) = fn unquote_splicing(args) -> f.(f).(unquote_splicing(args)) end
unquote(func)
end
tmp.(tmp)
end
end
def run do
ack =
fn_rec do
a(0, n) -> n + 1
a(m, 0) -> a.(m - 1, 1)
a(m, n) -> a.(m - 1, a.(m, n - 1))
end
ack.(3, 4)
end
end
IO.puts Foo.run
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment