import - 为什么 Erlang 既为模块提供 `import`,又为 header 提供 `include`?

标签 import erlang header-files

Erlang 的 -import() 指令允许您从其他模块导入代码。它的 include() 指令允许您从 header 导入代码。为什么有理由偏爱其中之一?

我的直觉是,当您不想限定 header 时,headers 适合于简短的、易于编译的代码,例如记录定义。

向您学习一些 Erlang 声明[1]“Erlang 头文件与它们的 C 对应部分非常相似:它们不过是添加到模块中的一段代码,就好像它是在第一个模块中编写的一样地方。”因此,包含似乎会导致编译器在不同模块之间重复工作。头文件似乎是强制性模块系统之上的可选复杂功能。那么我为什么要使用头文件呢?

[1] https://learnyousomeerlang.com/a-short-visit-to-common-data-structures

最佳答案

Erlang 的 -import 只允许您在没有 Module 的情况下调用导入的函数。它会损害易读性,不应使用:您需要检查 import 指令以了解函数是模块的本地函数还是外部函数。

使用头文件,您可以获得与 C 相同的功能,您可以使用它们来共享 -record 定义,而不是拥有类似 dto 的模块 (1),您可以使用它们来包含 -define 以使用相同的宏 (2)。

1:

-record(position, {x, y}).

假设您在整个代码中都有 #position{},而不是在所有地方定义记录并在记录定义更改时更新所有副本,您使用 header (或带有不透明类型,但这是另一个问题)。
我们只希望您记得更新所有副本,否则会出现困惑。

2:

-define(ENUM01, enum01).
-define(DEFAULT_TIMEOUT, 1000).

与其到处使用 enum011000,这很容易出错并且如果您需要更改它们需要多次更新,您可以在 header 中定义它们并将它们用作?ENUM01?DEFAULT_TIMEOUT

或者你可以在测试的时候更彻底:

-ifdef(TEST).
-define(assert(A), true = A).
-else
-define(assert(A), A).
-endif.

或者您可以包含一些有用的信息:

-define(LOG(Level, X), logger:log(Level, X, #{line => ?LINE}).

关于import - 为什么 Erlang 既为模块提供 `import`,又为 header 提供 `include`?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69065641/

相关文章:

python - 全局和本地导入

javascript - React 导入组件名称冲突

Erlang:如何向自己发送handle_info消息?

erlang - 停止 gen_server 时选择原因的语义是什么?

c - 即使在包含 <stdlib.h> 之后,'exit' 也会发出警告

c++ - 将其他 header 包含到包含类定义的 header 中

python - 导入并读取Python文件夹中的所有文件

haskell - 使用 ghc 是否可以导入未明确导出的符号?

sql - Erlang ODBC 连接挑战

c - 如何在不包含 C 头文件的情况下使用头文件中的函数?