Skip to content

Instantly share code, notes, and snippets.

@sasa1977
Last active December 12, 2015 04:18
Show Gist options
  • Select an option

  • Save sasa1977/4713324 to your computer and use it in GitHub Desktop.

Select an option

Save sasa1977/4713324 to your computer and use it in GitHub Desktop.
defmodule Lambda do
defrecord ParseResponse, code: nil, arity: 0 do
def new_list, do: new(code: [])
def push(response, this) do
this.
update_arity(max(response.arity, &1)).
update_code([response.code | &1])
end
def to_tuple(this), do: this.update_code(list_to_tuple(&1))
end
defmacro __f__({:<<>>, line, [string]}, _) do
case Code.string_to_ast!("{#{string}}", line) do
{:"{}", _, [code]} -> def_fun(parse_code(code))
{arity, code} -> def_fun(parse_code(code).arity(arity))
end
end
defmacro f(code) do
def_fun(parse_code(code))
end
defmacro f(arity, code) do
def_fun(parse_code(code).arity(arity))
end
defp def_fun(parse_result) do
quote do
fn(unquote_splicing(args(parse_result.arity))) ->
unquote(parse_result.code)
end
end
end
defp args(arity) do
Enum.map(0..arity, fn(arg) ->
{:"_#{arg}", [], nil}
end) |> tl
end
defp parse_code({:"&", _, [index]}) do
ParseResponse.new(
code: {:"_#{index}", [], nil},
arity: index
)
end
defp parse_code({:f, _, _} = inner), do: ParseResponse.new(code: inner)
defp parse_code(tuple) when is_tuple(tuple) do
parse_code(tuple_to_list(tuple)).to_tuple
end
defp parse_code(list) when is_list(list) do
List.foldr(list, ParseResponse.new_list, fn(element, parse_response) ->
parse_response.push(parse_code(element))
end)
end
defp parse_code(other), do: ParseResponse.new(code: other)
end
defrecord Rec, a: nil
defmodule Test do
import Lambda
def test_lambda do
# with f()
Enum.map(1..5, f(Rec.new(a: &1))) |>
Enum.each(f(IO.puts &1.a))
Enum.each(1..3, f(1, IO.puts "Hi!"))
# with %f
Enum.map(1..5, %f`Rec.new(a: &1)`) |>
Enum.each(%f(IO.puts &1.a))
Enum.each(1..3, %f(1, IO.puts "Hi!"))
end
end
Test.test_lambda
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment