を、マクロが(より安全-define(sub(X, Y), (X-Y))
ようになり-define(sub(X, Y), X-Y)
、)関数ではないのいずれかの明白な利点は、それができるということですカスタム関数呼び出しが禁止されているのでガードとして使用されます。
多くの場合、関数をインライン関数として定義する方が安全です。一方
は、何がしたいことは、最終的な場所にいくつかのローカルコンテキストを維持することですテストやショートカットでアサーションなどの他の興味深い例があります。
たとえば、のは、私は目的は「与えられたパターンに一致して、指定された値を返す、またはMミリ秒後に失敗」でのテストのための一般的なコールを作りたいとしましょう。
あなたが持ち歩くことができるデータ構造ではないので、コードでこの一般的なことをすることはできません。しかし、マクロで:
-define(wait_for(PAT, Timeout),
receive
PAT -> VAL
after Timeout ->
error(timeout)
end).
このマクロは、その後に使用することができます。これにより
my_test() ->
Pid = start_whatever(),
%% ...
?wait_for({'EXIT', Pid, Reason}, 5000),
?assertMatch(shutdown, Reason).
、私は、ネストの束を必要とすることなく、いくつかのテストでは、テキストの形を単純化することができますよ、そして機能では不可能な方法で。
はEUNITで定義されたアサーション自体が機能マクロを使用していることに注意してください、と。これは、同様にあなたがパターンとバインディングを運ぶとことはできませんでした空想のフォームを行うことができます
-define(assertMatch(PAT, TERM),
%% funs to avoid leaking bindings into parent scope
(fun() ->
try
PAT = TERM,
true
catch _:_ ->
error({assertion_failed, ?LINE, ...})
end
end)()).
に似て何かをしてくださいさもないと。
この最後のケースでは、?LINE
マクロを使用しています。これは、マクロのもう1つの利点です。コールサイトに関する情報や地域(モジュール名、行番号など)を保持しておくことです。これは、テストの失敗を報告しているときなど、そのようなメタデータが必要な場合に便利です。