Elixir学习笔记——模块属性

news2024/11/27 9:56:53

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 的工作原理,我们需要宏,因此我们将在元编程指南中重新讨论此模式,并学习如何使用模块属性作为自定义注释的存储。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1825785.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用GNU Gcov Lcov生成C++单元测试代码覆盖率报告

最近在统计C项目代码的单元测试覆盖率 发现通过gcov和lcov就能将代码单元测试覆盖率定量化和可视化 下面是基于gtest测试框架,对gcov和lcov生成覆盖率的简单示例 工作流程 主要有三个步骤 向GCC编译添加特殊的编译选项以生成可执行文件和*.gcno 运行&#xff08…

Vue3 生命周期函数及其与Vue2的对比总结

Vue3 继续保留了 Vue2 的生命周期钩子,但在 Composition API(setup 函数)中,它们被改为了一组导入函数。以下是它们的对比: Vue2 生命周期钩子和 Vue3 对应的生命周期函数: 在 Vue3 中,所有的…

TJA1145休眠唤醒调试

目录 项目场景:TJA1145引脚图问题描述SPI链路验证休眠唤醒休眠唤醒配置唤醒报文配置代码相关寄存器:模式寄存器使能CAN唤醒设置唤醒边沿检测事件状态及捕获寄存器CANFD报文不会被识别为有效的唤醒帧项目场景: 最近开发过程中,选择了这颗芯片,踩了很多坑,总算是把这个芯片…

【C语言】解决C语言报错:Undefined Reference

文章目录 简介什么是Undefined ReferenceUndefined Reference的常见原因如何检测和调试Undefined Reference解决Undefined Reference的最佳实践详细实例解析示例1:缺少函数定义示例2:函数声明和定义不匹配示例3:未链接必要的库示例4&#xff…

UWB技术定位系统源码,智慧工厂人员定位系统,独特的射频处理,配合先进的位置算法

UWB技术定位系统源码,高精度人员定位系统源码,智慧工厂人员定位系统源码,室内定位系统源码 本套系统运用UWB定位技术,开发的高精度人员定位系统,通过独特的射频处理,配合先进的位置算法,可以有…

人工智能在风险管理中的创新之路

随着科技的飞速发展,人工智能(AI)已经渗透到我们生活的方方面面,尤其在风险管理领域,其展现出的巨大潜力令人瞩目。风险管理,作为一个涉及广泛领域的复杂系统,正逐渐依赖于AI技术来提升效率和准…

Linux文件系统【真的很详细】

目录 一.认识磁盘 1.1磁盘的物理结构 1.2磁盘的存储结构 1.3磁盘的逻辑存储结构 二.理解文件系统 2.1如何管理磁盘 2.2如何在磁盘中找到文件 2.3关于文件名 哈喽,大家好。今天我们学习文件系统,我们之前在Linux基础IO中研究的是进程和被打开文件…

将Jar用三种方式生成Windows的安装程序

无论是WEB(spring boot)的JAR,还是JavaFX以及swing的Jar,要生成windows方式。 打包成Windows可执行文件(.exe),你可以使用以下三种方法: ### 方法1:使用Inno Setup 1. **构建JavaFX应用程序**: 使用M…

自制一个Linux live固件镜像ISO可引导系统

使用母盘镜像制作两个虚拟,来制作一个包含基本需求的filesystem.squashfs文件,具体看下面的链接 使用的安装镜像 是Linux Mint 制作好的成品 https://cloud.189.cn/t/U32Mvi7FnyA3 (访问码:2nbo) 最简单制作LIVE CD…

ChatGPT魔法背后的原理:如何做到词语接龙式输出?

介绍 我们都知道 ChatGPT 是 AIGC 工具,其实就是生成式人工智能。大家有没有想过这些问题 🤔️: 1、我们输入一段话,就可以看见它*噼里啪啦的一顿输出*,那么它的原理到底是什么? 2、到底它是怎么锁定这些…

【Prometheus】Prometheus的k8s部署

Kubernetes 集群部署 Prometheus 和 Grafana //实验环境 控制节点/master01 192.168.67.30 工作节点/node01 192.168.67.12 工作节点/node02 192.168.67.13 //node-exporter 安装 #创建监控 namespace kubectl create ns monitor-sa #部署 nod…

Java—装饰器模式

介绍 装饰器模式 装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许你动态地将行为添加到现有的对象中,而无需修改其代码。装饰器模式提供了比继承更灵活的功能扩展方式。 主要角色 Component:定义一个对…

【数据的增值之路】全生命周期的数据演化过程

引言:随着云计算、大数据、人工智能、区块链等新一代信息技术的快速发展,数据已经成为推动经济增长的重要生产要素。数据量的爆炸式增长,为挖掘数据价值、推动数字经济发展提供了丰富的资源基础。重要概念解析: 数据经济&#xf…

[图解]建模相关的基础知识-09

1 00:00:01,350 --> 00:00:03,780 首先,我们来看一下什么叫关系 2 00:00:05,370 --> 00:00:08,990 这个关系跟下面说的这些关系 3 00:00:09,000 --> 00:00:10,390 它不是一个东西 4 00:00:11,110 --> 00:00:14,950 比如说,我们UML类图上&…

【因果推断python】36_断点回归2

目录 RDD 估计 内核加权 RDD 估计 RDD 依赖的关键假设是阈值处潜在结果的平滑性。用比较正式地表述来说,当运行变量从右侧和左侧接近阈值时,潜在结果的极限应该是相同的。 如果这是真的,我们可以在阈值处找到因果关系 从其本身意义来说&…

RocketMQ源码学习笔记:源码启动NameServer,Broker

这是本人学习的总结,主要学习资料如下 马士兵教育rocketMq官方文档 目录 1、Overview2、NameServer2.1、源码启动NameServer 3、Broker启动过程 1、Overview 这篇文章的源码的版本是release-4.9.8。在启动各个模块之前应该先对项目进行打包mvn install -Dmaven.te…

大数据实训项目(小麦种子)-04、大数据实训项目JavaWeb环境搭建

文章目录 前言运行前准备工作1、安装Hadoop3.1.0配置winutils原因描述配置方式注意点(hadoop.dll拷贝System32目录下) 2、hive运行报错(The dir: /tmp/hive on HDFS should be writable. ) 项目环境搭建参考资料 前言 博主介绍&a…

【类脑计算】突触可塑性模型之Hebbian学习规则和STDP

1 引言 突触可塑性 (Synaptic plasticity)指经验能够修改神经回路功能的能力。特指基于活动修改突触传递强度的能力,是大脑适应新信息的主要调查机制。分为短期和长期突触可塑性,分别作用于不同时间尺度,对感官刺激的短期适应和长期行为改变…

unity数独游戏

using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI;public class MainMenuPanel : MonoBehaviour {public Button btnPlay; // 开始按钮public Slider sldDifficulty; // 难度滑动条private void Awake(){/…

省去烦恼!轻松实现一台电脑登录多个微信号的秘诀揭秘!

你知道如何在同一台电脑上登录多个微信号,并实现聚合聊天吗? 今天,我将分享一个多微管理神器——个微管理系统,帮助你解决这一问题! 1、多号同时登录,聚合聊天 无论你有多少个微信号,都可以一…