Types 类型规范是否属于.hrl文件?

Types 类型规范是否属于.hrl文件?,types,erlang,header-files,specifications,Types,Erlang,Header Files,Specifications,Erlang类型规范是属于.hrl文件(加载到任何需要它们的.erl文件中)还是应该保存在Erlang模块中,然后导出(这样可以在其他模块中使用)?在我看来,这两种方法都能实现同样的目标 有什么细微的差别我错过了吗?(我知道头文件的内容被复制到每个使用它们的文件中,基本上是在编译时复制代码) 有没有一种方法比另一种方法更适用 提前谢谢 没那么重要。你可以把它们放在有意义的地方 如果您的类型与记录定义密切相关,并且应该知道它们的内部结构,请将它们放入.hrl文件中 如果您不想公开内部结构(例

Erlang类型规范是属于.hrl文件(加载到任何需要它们的.erl文件中)还是应该保存在Erlang模块中,然后导出(这样可以在其他模块中使用)?在我看来,这两种方法都能实现同样的目标

  • 有什么细微的差别我错过了吗?(我知道头文件的内容被复制到每个使用它们的文件中,基本上是在编译时复制代码)
  • 有没有一种方法比另一种方法更适用

提前谢谢

没那么重要。你可以把它们放在有意义的地方

  • 如果您的类型与记录定义密切相关,并且应该知道它们的内部结构,请将它们放入.hrl文件中
  • 如果您不想公开内部结构(例如,您使用了PropList,但希望将来更改为dicts),则最好使用访问器函数创建模块,并将类型规范放在其中,并附上注释:“不要依赖于此类型内部结构”。您仍然希望导出它,以确保其他模块使用它。甚至,如果他们把它当作一个黑匣子

如果你在.hrl和其他模块中添加了一些依赖于它的内容,那么就很难进行更改。当你们把它放在模块中时,修改和重构应该更容易。

这没什么大不了的。你可以把它们放在有意义的地方

  • 如果您的类型与记录定义密切相关,并且应该知道它们的内部结构,请将它们放入.hrl文件中
  • 如果您不想公开内部结构(例如,您使用了PropList,但希望将来更改为dicts),则最好使用访问器函数创建模块,并将类型规范放在其中,并附上注释:“不要依赖于此类型内部结构”。您仍然希望导出它,以确保其他模块使用它。甚至,如果他们把它当作一个黑匣子

如果你在.hrl和其他模块中添加了一些依赖于它的内容,那么就很难进行更改。当您将其放入模块中时,应该更容易修改和重构。

这确实有点重要,因为规范实际上用于生成edoc应用程序的函数/模块文档

如果right spec子句不在right function子句之上,edoc将发出抱怨,整个模块的文档生成将失败


请考虑一下edoc。

这确实有点重要,因为规范实际上用于生成edoc应用程序的函数/模块文档

如果right spec子句不在right function子句之上,edoc将发出抱怨,整个模块的文档生成将失败

请考虑edoc。

类型规范(即
-spec
属性)属于定义函数的模块。句号

另一方面,类型定义(
-Type
-opaque
)可以在
.hrl
文件中定义,但我认为这通常是一个糟糕的决定。这意味着,包括所讨论的头的每个模块都将在本地“定义”类型。这可能会导致命名空间冲突,因为模块已经定义了一个类型,而该类型也定义在要包含的头中。 从模块导出类型而不是在
中定义它们。hrl
s为您提供名称空间前缀,并消除本地(
mytype()
)定义的类型与外部应用程序/模块定义的类型之间的歧义(
yourmod:yourtype()
或,原文如此,
yourmod:mytype()

通常,在编写Erlang应用程序或库时,最好在使用它的模块中定义类型(最多)。对于在库外部导出的类型,请从主库模块导出它们-如果该应用程序名为
myapp
,则使所有公共类型都可以访问,如
myapp:config()
myapp:some_record()

我想到的还有一件事:透析器不喜欢简单的记录定义——建议明确定义记录的类型(因此每个
-record
都有一个
-type
)。另一方面,在头文件中放置记录定义很方便,因此它们可以在不同位置的代码之间共享(如
src/mymod.erl
test/mymod\u tests.erl
)。在这种情况下,我会在头文件中定义记录(
src/mymod.hrl
用于私有模块,或者
include/mymod.hrl
,如果模块是应用程序/库公共接口的一部分),但仍然会从它所属的模块中定义和导出类型(即
mymod:some_record()

tkowal提出的观点也很重要。如果您不想公开内部结构,那么
-opaque
属性就是为了做到这一点,它表示“不依赖于此类型的内部结构”。因此,您只需使用
-opaque
而不是
-type
定义一个类型,将其导出,并让透析器在代码中的每个位置向您发出警告,这些位置意外地构建了该类型的术语,但未明确说明,或者关于试图在定义类型的模块外部解构该类型的每个模式匹配。

类型规范(即
-spec
属性)属于定义函数的模块。句号

另一方面,类型定义(
-Type
-opaque
)可以在
.hrl
文件中定义,但我认为这通常是一个糟糕的决定。这意味着,包括所讨论的头的每个模块都将在本地“定义”类型。这可能会导致命名空间冲突,因为模块已经定义了一个类型,而该类型也定义在要包含的头中。 从模块中导出类型而不是在
.hrl
s中定义它们会为您提供名称空间前缀并消除歧义