gpt4 book ai didi

macros - 如何通过 Erlang 的预处理器有条件地排除整个子句?

转载 作者:行者123 更新时间:2023-12-02 19:09:02 24 4
gpt4 key购买 nike

我正在用 Erlang 编写一些模块,应该在各种 OTP 版本上编译。在某些情况下,我想使用旧版本中不受支持的 ++ 运算符模式,但前提是它可用。因此,我对这项任务的尝试如下:

f([]) -> empty;
f([_|_]) -> cons;
-if(?OTP_RELEASE >= 23).
f([] ++ _) -> empty_append;
-endif.
f(X) -> error(nah).

我发现的解决此问题的方法是:

  • 将 iffed 子句移到开头。然而,这在以下情况下效果不佳:

    • 我需要添加更多的-if
    • 条款的顺序禁止我出于任何原因这样做。
  • 创建一个美丽的 ifels 花园,将整个功能复制多次。显然,这并没有通过。

有什么方便的方法吗?如果可能的话,我希望能有一个通用的解决方案,而不仅限于所提供的案例。

最佳答案

来自 flow control in macros : The macro directives cannot be used inside functions.所以如果你想使用 -ifdef您需要多次复制相同的功能。

(我想这与它们被定义在 -. 之间有关)

话虽这么说,你可以这样做:

f([]) -> empty;
f([_|_]) -> cons;
f([] ++ _) when ?OTP_RELEASE >= 23 -> empty_append;
f(X) -> error(nah).

您可以使用 erlc -S <module> 验证永远不会匹配的子句已从生成的 beam ASM 代码中删除。 .此外,编译器将显示警告。

这一步产生的警告不能选择性省略。来自 here :

Another class of warnings is generated by the compiler during optimization and code generation. They warn about patterns that will never match (such as a=b), guards that always evaluate to false, and expressions that always fail (such as atom+42).

Those warnings cannot be disabled (except by disabling all warnings).

如果你想完全避免警告,你需要类似的东西(请注意,这种风格不会删除分支,因为 OtpRelease 是一个变量):

f(Term) ->
f(Term, ?OTP_RELEASE).

f([], _) -> empty;
f([_|_], _) -> cons;
f([] ++ _, OtpRelease) when OtpRelease >= 23 -> empty_append;
f(_, _) -> error(nah).

编辑:在最后一个示例中,OTP23 的代码优化器能够删除无法访问的代码。在这种特殊情况下,如果 f/2未导出,其第 3 或第 4 个子句将根据 ?OTP_RELEASE 删除)

关于macros - 如何通过 Erlang 的预处理器有条件地排除整个子句?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64609631/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com