In diesem Fall ist die eine offensichtliche Vorteil der Makro keine Funktion (-define(sub(X, Y), X-Y)
, die sicherer als -define(sub(X, Y), (X-Y))
wäre) ist, dass es sein kann, Wird als Wächter verwendet, da benutzerdefinierte Funktionsaufrufe verboten sind.
In vielen Fällen wäre es sonst sicherer, die Funktion als Inline zu definieren.
Auf der anderen Seite gibt es andere interessante Fälle, z. B. Assertionen in Tests oder Verknüpfungen, wo Sie wollen, dass einige lokale Kontext an der endgültigen Stelle zu halten.
Nehmen wir zum Beispiel an, ich möchte einen generischen Aufruf für einen Test machen, bei dem das Ziel "ein gegebenes Muster übereinstimmt und einen gegebenen Wert zurückgibt oder nach M Millisekunden fehlschlägt".
Ich kann dies nicht generisch mit Code machen, da Muster keine Datenstrukturen sind, die Sie herumtragen dürfen. Doch mit Makros:
-define(wait_for(PAT, Timeout),
receive
PAT -> VAL
after Timeout ->
error(timeout)
end).
Dieses Makro kann dann verwendet werden, wie:
my_test() ->
Pid = start_whatever(),
%% ...
?wait_for({'EXIT', Pid, Reason}, 5000),
?assertMatch(shutdown, Reason).
Dadurch dies, ich bin in der Lage, die Form von Text in einigen Tests zu vereinfachen, ohne ein Bündel von Verschachtelung zu benötigen und auf eine Weise, die mit Funktionen nicht möglich ist.
Sie beachten, dass die Behauptung selbst, wie durch eunit definiert eine Funktion Makro verwendet, und tut so etwas wie
-define(assertMatch(PAT, TERM),
%% funs to avoid leaking bindings into parent scope
(fun() ->
try
PAT = TERM,
true
catch _:_ ->
error({assertion_failed, ?LINE, ...})
end
end)()).
Diese Sie tragen Muster und Bindungen und tun Phantasie Formen ähnlich lässt, die nicht möglich sein könnte, Andernfalls.
In diesem letzten Fall werden Sie bemerken, dass ich das ?LINE
Makro verwendet habe. Das ist ein weiterer Vorteil von Makros: Sie bewahren Informationen und Orte über die Aufruf-Site auf, z. B. den Modulnamen, die Zeilennummer usw. Dies ist nützlich, wenn solche Metadaten erforderlich sind, z. B. wenn Sie Testfehler melden.