Elixir学习笔记——模块属性

Elixir 中的模块属性有三个用途:

1.作为模块和函数注释
2.作为编译期间使用的临时模块存储
3.作为编译时常量

让我们检查一下这些示例。

作为注释

Elixir 引入了 Erlang 中的模块属性概念。例如:

在上面的例子中,我们使用模块属性语法定义模块文档。Elixir 有一些保留属性。以下是其中一些最常用的属性:

@moduledoc — 为当前模块提供文档。
@doc — 为属性后面的函数或宏提供文档。
@spec — 为属性后面的函数提供类型规范。
@behaviour —(注意英国拼写)用于指定 OTP 或用户定义的行为。
@moduledoc 和 @doc 是迄今为止最常用的属性,我们希望您经常使用它们。Elixir 将文档视为first-class,并提供了许多访问文档的函数。我们将在它们自己的章节中介绍它们。

让我们回到前面章节中定义的 Math 模块,添加一些文档并将其保存到 math.ex 文件中:

Elixir 提倡使用带有 heredocs 的 Markdown 来编写可读的文档。Heredocs 是多行字符串,它们以三重双引号开头和结尾,保持内部文本的格式。我们可以直接从 IEx 访问任何已编译模块的文档:

我们还提供了一个名为 ExDoc 的工具,用于从文档生成 HTML 页面。

您可以查看 Module 的文档,了解受支持属性的完整列表。Elixir 还使用属性通过 typespecs 注释我们的代码。

作为临时存储

到目前为止,我们已经了解了如何定义属性,但如何读取它们呢?让我们看一个例子:

注意:
不要在属性和其值之间添加换行符,否则 Elixir 会认为您正在读取值,而不是设置值。

尝试访问未定义的属性将打印警告:

defmodule MyServer do
  @unknown
end
warning: undefined module attribute @unknown, please remove access to @unknown or explicitly set it before access

也可以在函数内部读取属性:

模块属性是在编译时定义的,其返回值(而不是函数调用本身)将替代属性。因此,上述代码将有效地编译为:

这对于预先计算值,然后将其结果注入模块非常有用。这就是我们所说的临时存储:模块编译后,模块属性将被丢弃,但已读取该属性的函数除外。请注意,您不能将在同一模块中定义的函数作为属性本身的一部分来调用,因为这些函数尚未定义。

每次我们在函数内读取属性时,Elixir 都会对其当前值进行快照。因此,如果您在多个函数内多次读取相同的属性,最终会增加编译时间,因为 Elixir 现在必须编译每个快照。一般来说,您希望避免多次读取相同的属性,而是将其移动到函数中。例如,不要这样:

最好这样:

作为编译时常量

模块属性也可用作编译时常量。一般来说,函数本身足以充当代码库中的常量。例如,无需定义:

您应该更喜欢:

如果需要在模块之间共享,您甚至可以定义一个公共函数。在许多项目中,通常有一个名为 MyApp.Constants 的模块,它定义整个代码库中使用的所有常量。

您甚至可以将复合数据结构作为常量,只要它们完全由其他数据类型组成(没有函数调用、没有运算符,也没有其他表达式)。例如,您可以按如下方式指定系统配置常量:

鉴于 Elixir 中的数据结构是不可变的,因此,只要它没有任何可执行表达式,则只会分配上述数据结构的单个实例并在所有函数调用之间共享。

当您需要在编译时执行某些工作,然后将其结果注入函数内部时,就会出现模块属性的用例。一种常见的情况是模式和保护内部的模块属性(作为 defguard/1 的替代方案),因为它们仅支持一组有限的表达式:

模块属性作为常量和临时存储最常一起使用:模块属性用于计算和存储很重要的值,然后从该模块中公开为常量。

更进一步

库和框架可以利用模块属性来提供自定义注释。要查看示例,只需查看 Elixir 的单元测试框架 ExUnit 即可。ExUnit 将模块属性用于多种不同的目的:

在上面的示例中,ExUnit 将 async: true 的值存储在模块属性中以更改模块的编译方式。标签也可以用作注释,并且可以多次提供,这要归功于 Elixir 累积属性的能力。然后,您可以使用标签来设置和过滤测试,例如在 Windows 上运行测试套件时避免执行特定于 Unix 的测试。

要完全理解 ExUnit 的工作原理,我们需要宏,因此我们将在元编程指南中重新讨论此模式,并学习如何使用模块属性作为自定义注释的存储。

在接下来的章节中,我们将探索结构和协议,然后转到异常处理和其他结构,如符号和理解。

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值