I have a function that looks something like this.
def test(options \\ []) do
# Fun stuff happens here :)
end
It accepts several (optional) keyword arguments, including do:
. I'd like to be able to call it like this.
test foo: 1 do
"Hello"
end
However, this gives an error.
** (UndefinedFunctionError) function Example.test/2 is undefined or private. Did you mean one of: * test/0 * test/1 Example.test([foo: 1], [do: "Hello"]) (elixir) lib/code.ex:376: Code.require_file/2
As you can see from the error, the syntax above is desugaring to two separate keyword lists. Now, I can call this function using the following slightly inconvenient syntax
Example.test foo: 1, do: (
"Hello"
)
but is there any way to provide a do
-block in addition to other keyword arguments in one function call?
If you are open to using a macro instead of a function this might help you:
defmodule Example do
defmacro test(args, do: block) do
quote do
IO.inspect(unquote(args))
unquote(block)
end
end
end
Sample usage:
iex(2)> defmodule Caller do
...(2)> require Example
...(2)>
...(2)> def foo do
...(2)> Example.test foo: 1 do
...(2)> IO.puts "Inside block"
...(2)> end
...(2)> end
...(2)> end
{:module, Caller,
<<70, 79, 82, 49, 0, 0, 4, 108, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 147,
0, 0, 0, 16, 13, 69, 108, 105, 120, 105, 114, 46, 67, 97, 108, 108, 101, 114,
8, 95, 95, 105, 110, 102, 111, 95, 95, ...>>, {:foo, 0}}
iex(3)> Caller.foo
[foo: 1]
Inside block
:ok