defp kl_i([k, v | t]) do
quote do
[
{unquote(Macro.escape(k)), unquote v}
| unquote kl_i t
]
end
end
defp kl_i([]), do: quote do: []
defmacro kl(l), do: kl_i l
# usage
IO.inspect kl [a, 2 + 7, b, 6]
# => [{{:a, [line: 16], nil}, 9}, {{:b, [line: 16], nil}, 6}]
Note: Elixir's syntax does get in the way a bit here, the `a` and `b` are converted into nullary calls, you could use a different escaping function to fix this defp escape_key({v1, v2}), do: {escape_key(v1), escape_key(v2)}
defp escape_key({:{}, pos, els}) when is_list(pos), do: {:{}, pos, Enum.map(els, &escape_key/1)}
defp escape_key(els) when is_list(els), do: Enum.map(els, &escape_key/1)
defp escape_key({sym, pos, nil}) when is_list(pos), do: Macro.escape sym
This actually has different behavior because the ref allocation is under a big lambda (Λ). Each time it is applied it would generate a new ref cell. So it would generate a `ref (bool → bool)` starting with `λx. x` and assign `not` to it. Then generate a separate `ref (int → int)` (again starting with `λx. x`) and dereference and apply it. Thus this would print `23`.
(The naive model of) SML runs into problems because it erases the big lambdas and so evaluates `Λα. ref [α → α] (λx. x)` to a single ref cell of type `∀α. ref (α → α)`
Sidenote: Variance does have some relation here, I couldn't think of a way to trigger bad behavior without a type that uses the type variable invariantly.