I am looking at the following code:
How can I refactor this not to have to define the same thing twice for def
and defp
? I want to add more code here also.
I am looking at the following code:
How can I refactor this not to have to define the same thing twice for def
and defp
? I want to add more code here also.
What’s important to note here is that def
and defp
are macros - they are not keywords. So when we define functions using def/defp we use the normal syntax for calling macros (or functions).
That means we can do this:
method = :def
unquote(method)(unquote(origname)(unquote_splicing(args))) do
...
end
I get this error
** (CompileError) iex:118: invalid call unquote(method)(unquote(origname)(unquote_splicing(args))) do
…
It works on my machine:
iex(1)> method = :def
:def
iex(2)> origname = :my_func
:my_func
iex(3)> args = [:arg1, :arg2]
[:arg1, :arg2]
iex(4)> quote(do: unquote(method)(unquote(origname)(unquote_splicing(args))))
{:def, [], [{:my_func, [], [:arg1, :arg2]}]}
iex(5)> quote(do: unquote(method)(unquote(origname)(unquote_splicing(args))) do ... end)
{:def, [], [{:my_func, [], [:arg1, :arg2]}, [do: {:..., [], Elixir}]]}
Can you show the code that causes the compilation error?
EDIT: A better example of it working:
iex(4)> defmodule Foo do
...(4)> defmacro foo(method, origname, args) do
...(4)> quote do
...(4)> unquote(method)(unquote(origname)(unquote_splicing(args))) do :bar end
...(4)> end
...(4)> end
...(4)> end
iex(5)> require Foo
Foo
iex(6)> defmodule Bar do
...(6)> Foo.foo(:def, :bar, [:arg1])
...(6)> end
{:module, Bar,
<<70, 79, 82, 49, 0, 0, 4, 20, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 126,
0, 0, 0, 14, 10, 69, 108, 105, 120, 105, 114, 46, 66, 97, 114, 8, 95, 95,
105, 110, 102, 111, 95, 95, 7, 99, 111, ...>>, {:bar, 1}}
iex(7)> Bar.bar(:arg1)
:bar
You can’t do unquote(method)
if method
is in the list of bind_quote
d variables. Remove it from bind_quote
and it may work.
I just tried but I still get the same issue.
I am trying to reproduce the error using your repository but I can’t. Are there tests covering this code?
Not yet that is my next step.
iex -S mix
Cachex.start(:mycache)
defmodule M do
use Cachex.Memoize
defmemo f(x), cache: :mycache do
x + 1
end
end
Okay I added a test the code is on top of the master branch https://github.com/edescourtis/cachex .
You can run the test directly with mix test test/cachex/memoize_test.exs