def
の周りにquote
がありません。また、def
の中のマップ更新式の値を引用符で囲む必要があります。
defmacro __using__(_) do
Enum.map ~w(public private), fn value ->
quote do
def unquote(:"make_#{value}")(user = %User{}) do
%{user | privacy: unquote(value)}
end
end
end
end
はテスト::
defmodule User do
defstruct [:privacy]
end
defmodule A do
defmacro __using__(_) do
Enum.map ~w(public private), fn value ->
quote do
def unquote(:"make_#{value}")(user = %User{}) do
%{user | privacy: unquote(value)}
end
end
end
end
end
defmodule B do
use A
end
iex(1)> %User{} |> B.make_public
%User{privacy: "public"}
編集:コメントで要求された変更を:そして最後に、あなたは__using__/1
が構築ASTを返すように、ここでは代わりのEnum.each
Enum.map
を使用する必要があります
defmacro __using__(_) do
Enum.map ~w(public private), fn value ->
quote do
def unquote(:"make_#{value}")(user = %User{}) do
%{user | privacy: unquote(value)}
end
def unquote(:"make_#{String.upcase(value)}")(user = %User{}) do
%{user | privacy: unquote(String.upcase(value))}
end
end
end
end
iex(1)> %User{} |> B.make_public
%User{privacy: "public"}
iex(2)> %User{} |> B.make_PUBLIC
%User{privacy: "PUBLIC"}
iex(3)> %User{} |> B.make_private
%User{privacy: "private"}
iex(4)> %User{} |> B.make_PRIVATE
%User{privacy: "PRIVATE"}
しかし、動的に生成された 'def'と同じレベルに関数を追加する必要がある場合はどうすればよいですか? – Moldaone
'quote'の中に任意の数の' def'を置くことができます。 – Dogbert
問題は、 '__using__'関数が定義のASTリストを期待しているので、複数の' quote'を宣言すると、最後のものだけが取られます。 – Moldaone