Elixir学习笔记——别名、需要、导入和使用

2024-06-15 19:04

本文主要是介绍Elixir学习笔记——别名、需要、导入和使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

为了便于软件重用,Elixir 提供了三个指令(alias、require 和 import)以及一个名为 use 的宏,总结如下:

# 为模块添加别名,以便可以将其称为 Bar 而不是 Foo.Bar
alias Foo.Bar, as: Bar

# 需要模块才能使用其宏
require Foo

# 从 Foo 导入函数,以便可以在不带 `Foo.` 前缀的情况下调用它们
import Foo

# 调用 Foo 中定义的自定义代码作为扩展点
use Foo

我们现在将详细探讨它们。请记住,前三个被称为指令,因为它们具有词法范围,而 use 是一个允许使用的模块注入代码的通用扩展点。

别名

alias 允许您为任何给定的模块名称设置别名。

假设一个模块使用 Math.List 中实现的专用列表。alias 指令允许在模块定义中将 Math.List 引用为 List:

原始 List 仍可通过完全限定名称 Elixir.List 在 Stats 中访问。

Elixir 中定义的所有模块都在主 Elixir 命名空间内定义,例如 Elixir.String。但是,为了方便起见,您可以在引用它们时省略“Elixir。”

别名经常用于定义快捷方式。事实上,调用不带 :as 选项的 alias 会自动将别名设置为模块名称的最后一部分,例如:

与以下相同:

请注意,alias 是词法作用域,这允许您在特定函数内设置别名:

在上面的例子中,由于我们在函数 plus/2 内调用 alias,因此别名仅在函数 plus/2 内有效。minus/2 不会受到影响。

需要

Elixir 提供宏作为元编程(编写代码生成代码)的机制。宏在编译时展开。

模块中的公共函数是全局可用的,但为了使用宏,您需要通过要求定义它们的模块来选择加入。

iex>  Integer.is_odd(3)
** (UndefinedFunctionError) function Integer.is_odd/1 is undefined or private. However, there is a macro with the same name and arity. Be sure to require Integer if you intend to invoke this macro
    (elixir) Integer.is_odd(3)
iex>  require Integer
Integer
iex>  Integer.is_odd(3)
true

在 Elixir 中,Integer.is_odd/1 被定义为宏,以便可以将其用作保护。这意味着,为了调用 Integer.is_odd/1,我们需要首先要求 Integer 模块。

请注意,与 alias 指令一样,require 也是词法作用域。我们将在后面的章节中详细讨论宏。

导入

每当我们想从其他模块访问函数或宏而不使用完全限定名称时,我们都会使用 import。请注意,我们只能导入公共函数,因为私有函数永远无法从外部访问。

例如,如果我们想多次使用 List 模块中的 duplicate/2 函数,我们可以导入它:

我们只从 List 导入了函数 duplicate(参数为 2)。虽然 :only 是可选的,但建议使用它,以避免在当前范围内导入给定模块的所有函数。:except 也可以作为选项提供,以便导入模块中除函数列表之外的所有内容。

请注意,import 也是词法范围的。这意味着我们可以在函数定义中导入特定的宏或函数:

在上面的例子中,导入的 List.duplicate/2 仅在该特定函数中可见。duplicate/2 在该模块(或任何其他模块)的任何其他函数中都不可用。

虽然导入对于框架和库构建抽象很有用,但开发人员通常应该更喜欢在自己的代码库中使用别名进行导入,因为别名使被调用函数的来源更清晰。

使用

use 宏经常用作扩展点。这意味着,当您使用模块 FooBar 时,您允许该模块在当前模块中注入任何代码,例如导入自身或其他模块、定义新函数、设置模块状态等。

例如,为了使用 ExUnit 框架编写测试,开发人员应该使用 ExUnit.Case 模块:

在后台,use 需要给定的模块,然后对其调用 __using__/1 回调,允许模块将一些代码注入当前上下文。一些模块(例如,上面的 ExUnit.Case,还有 Supervisor 和 GenServer)使用此机制为您的模块填充一些基本行为,您的模块旨在覆盖或完成这些行为。

一般来说,以下模块:

编译为

由于 use 允许运行任何代码,因此如果不阅读其文档,我们无法真正了解使用模块的副作用。因此,请谨慎使用此功能,并且仅在严格需要时才使用。不要在可以使用导入或别名的地方使用 use。

理解别名

此时,您可能想知道:Elixir 别名到底是什么,它是如何表示的?

Elixir 中的别名是一个大写的标识符(如字符串、关键字等),在编译期间会转换为原子。例如,String 别名默认转换为原子 :"Elixir.String":

通过使用 alias/2 指令,我们可以改变别名扩展为的原子。

别名扩展为原子,因为在 Erlang 虚拟机(以及 Elixir)中,模块始终由原子表示:

这是我们用来调用 Erlang 模块的机制:

模块嵌套

既然我们已经讨论了别名,我们可以讨论嵌套以及它在 Elixir 中的工作原理。请考虑以下示例:

上面的示例将定义两个模块:Foo 和 Foo.Bar。只要它们在同一个词法范围内,第二个模块就可以在 Foo 内作为 Bar 访问。

如果稍后将 Bar 模块移出 Foo 模块定义,则必须通过其全名 (Foo.Bar) 引用它,或者必须使用上面讨论的别名指令设置别名。

注意:在 Elixir 中,您不必在定义 Foo.Bar 模块之前定义 Foo 模块,因为它们实际上是独立的。上面的代码也可以写成:

为嵌套模块添加别名不会将父模块纳入范围。请考虑以下示例:

正如我们将在后面的章节中看到的那样,别名在宏中也起着至关重要的作用,以确保它们是健壮的结构。

多别名/导入/需要/使用

可以同时为多个模块设置别名、导入、要求或使用多个模块。当我们开始嵌套模块时,这尤其有用,这在构建 Elixir 应用程序时非常常见。例如,假设您有一个应用程序,其中所有模块都嵌套在 MyApp 下,您可以同时为模块 MyApp.Foo、MyApp.Bar 和 MyApp.Baz 设置别名,如下所示:

至此,我们完成了对 Elixir 模块的介绍。下一个要介绍的主题是模块属性。

这篇关于Elixir学习笔记——别名、需要、导入和使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1064312

相关文章

Java使用HttpClient实现图片下载与本地保存功能

《Java使用HttpClient实现图片下载与本地保存功能》在当今数字化时代,网络资源的获取与处理已成为软件开发中的常见需求,其中,图片作为网络上最常见的资源之一,其下载与保存功能在许多应用场景中都... 目录引言一、Apache HttpClient简介二、技术栈与环境准备三、实现图片下载与保存功能1.

Python中使用uv创建环境及原理举例详解

《Python中使用uv创建环境及原理举例详解》uv是Astral团队开发的高性能Python工具,整合包管理、虚拟环境、Python版本控制等功能,:本文主要介绍Python中使用uv创建环境及... 目录一、uv工具简介核心特点:二、安装uv1. 通过pip安装2. 通过脚本安装验证安装:配置镜像源(可

LiteFlow轻量级工作流引擎使用示例详解

《LiteFlow轻量级工作流引擎使用示例详解》:本文主要介绍LiteFlow是一个灵活、简洁且轻量的工作流引擎,适合用于中小型项目和微服务架构中的流程编排,本文给大家介绍LiteFlow轻量级工... 目录1. LiteFlow 主要特点2. 工作流定义方式3. LiteFlow 流程示例4. LiteF

使用Python开发一个现代化屏幕取色器

《使用Python开发一个现代化屏幕取色器》在UI设计、网页开发等场景中,颜色拾取是高频需求,:本文主要介绍如何使用Python开发一个现代化屏幕取色器,有需要的小伙伴可以参考一下... 目录一、项目概述二、核心功能解析2.1 实时颜色追踪2.2 智能颜色显示三、效果展示四、实现步骤详解4.1 环境配置4.

使用jenv工具管理多个JDK版本的方法步骤

《使用jenv工具管理多个JDK版本的方法步骤》jenv是一个开源的Java环境管理工具,旨在帮助开发者在同一台机器上轻松管理和切换多个Java版本,:本文主要介绍使用jenv工具管理多个JD... 目录一、jenv到底是干啥的?二、jenv的核心功能(一)管理多个Java版本(二)支持插件扩展(三)环境隔

SQL中JOIN操作的条件使用总结与实践

《SQL中JOIN操作的条件使用总结与实践》在SQL查询中,JOIN操作是多表关联的核心工具,本文将从原理,场景和最佳实践三个方面总结JOIN条件的使用规则,希望可以帮助开发者精准控制查询逻辑... 目录一、ON与WHERE的本质区别二、场景化条件使用规则三、最佳实践建议1.优先使用ON条件2.WHERE用

Java中Map.Entry()含义及方法使用代码

《Java中Map.Entry()含义及方法使用代码》:本文主要介绍Java中Map.Entry()含义及方法使用的相关资料,Map.Entry是Java中Map的静态内部接口,用于表示键值对,其... 目录前言 Map.Entry作用核心方法常见使用场景1. 遍历 Map 的所有键值对2. 直接修改 Ma

MySQL 衍生表(Derived Tables)的使用

《MySQL衍生表(DerivedTables)的使用》本文主要介绍了MySQL衍生表(DerivedTables)的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学... 目录一、衍生表简介1.1 衍生表基本用法1.2 自定义列名1.3 衍生表的局限在SQL的查询语句select

Mybatis Plus Join使用方法示例详解

《MybatisPlusJoin使用方法示例详解》:本文主要介绍MybatisPlusJoin使用方法示例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,... 目录1、pom文件2、yaml配置文件3、分页插件4、示例代码:5、测试代码6、和PageHelper结合6

MySQL分区表的具体使用

《MySQL分区表的具体使用》MySQL分区表通过规则将数据分至不同物理存储,提升管理与查询效率,本文主要介绍了MySQL分区表的具体使用,具有一定的参考价值,感兴趣的可以了解一下... 目录一、分区的类型1. Range partition(范围分区)2. List partition(列表分区)3. H