文档章节

elixir官方入门教程 别名,要求与进口

ljzn
 ljzn
发布于 2016/08/04 20:55
字数 1791
阅读 266
收藏 1

#别名,要求与进口

1. 别名
2. 要求
3. 进口
4. 使用
5. 理解别名
6. 模块嵌套
7. 群体别名/进口/要求/使用

为了方便软件复用,Elixir提供了三个命令(alias,requireimport)外加一个宏use,简介如下:

# 给模块一个别名,使得我们可以调用Bar来代替Foo.Bar
alias Foo.Bar, as: Bar

# 确保模块是编译好且可用的(常用于宏)
require Foo

# 进口Foo中的函数,使得可以不加前缀地调用它们
import Foo

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

现在我们将详细探索它们.记住前三条之所以被称为命令,是因为它们具有词法范围,而use只是一个普通扩展点.

#别名

alias允许你为任何具名模块赋予别名.想象一下我们的Math模块要使用一个特殊的列表执行方法来做特定的数学操作:

defmodule Math do
  alias Math.List, as: List
end

从现在起,任何提到List的地方都会自动扩展成Math.List.如果有人想访问原始的List,就需要在之前加上模块名Elixir.:

List.flatten             #=> uses Math.List.flatten
Elixir.List.flatten      #=> uses List.flatten
Elixir.Math.List.flatten #=> uses Math.List.flatten

所有在Elixir中定义的模块,都定义在一个主要Elixir命名空间中.为了方便,在调用它们时你可以省略"Elixir".

别名经常用于定义缩写.事实上,调用alias时不带:as,就会自动将模块名的最后部分设为别名.例如:

alias Math.List

等同于

alias Math.List, as: List

注意alias确定了语法范围,能让你在特定的函数中设置别名:

defmodule Math do
  def plus(a, b) do
    alias Math.List
    # ...
  end

  def minus(a, b) do
    # ...
  end
end

在上述例子中,由于我们是在plus/2函数中调用的alias,所以别名只在函数plus/2中可用.对minus/2没有影响.

#要求

Elixir提供了宏作为元编程的机制(编写能生成代码的代码).

宏是在编译时执行和扩展的代码块.这意味着,为了使用一个宏,我们要保证它的模块和实现都在编译过程中可用.这通过require命令完成:

iex> Integer.is_odd(3)
** (CompileError) iex:1: you must require Integer before invoking the macro Integer.is_odd/1
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函数,我们可以简单地进口它:

iex> import List, only: [duplicate: 2]
List
iex> duplicate :ok, 3
[:ok, :ok, :ok]

这时,我们只进口了List模块中的duplicate函数(带两个参数).选项:only的作用是避免将模块中的所有函数都导入命名空间中,选项:except的作用是将模块中除了列表里的其它所有函数都导入.

import也支持将:only设置为:macros:functions.例如,想要进口所有宏,可以这样写:

import Integer, only: :macros

或者进口所有函数:

import Integer, only: :functions

注意import也有语法范围.这意味着我们可以在函数定义中进口特定的宏或函数:

defmodule Math do
  def some_function do
    import List, only: [duplicate: 2]
    duplicate(:ok, 10)
  end
end

在上述例子中,进口的List.duplicate/2只在这个特定的函数中时可见的.duplicate/2在这个模块中的其它任何函数中都是不可用的(或其它任何模块).

注意import一个模块就自动require了它.

#使用

虽然不是一个命令,但use是一个与require紧密关联的宏,能让你在当前内容中使用一个模块.开发者们经常用use宏来往当前语法空间中添加外部功能,通常是模块.

例如,为了使用ExUnit框架来写测试,开发者需要使用ExUnit.Case模块:

defmodule AssertionTest do
  use ExUnit.Case, async: true

  test "always pass" do
    assert true
  end
end

在幕后,use会要求给定的模块,然后在其中调用__using__/1反馈,允许模块往当前内容注入一些代码.一般来说,下面的模块:

defmodule Example do
  use Feature, option: :value
end

被编译成

defmodule Example do
  require Feature
  Feature.__using__(option: :value)
end

至此我们关于Elixir模块的介绍几乎结束了.最后的话题是模块属性.

#理解别名

这时,你可能会想知道:究竟什么是Elixir中的别名,它是如何运作的?

Elixir中的别名是首字母大写的id(例如String,Keyword等等),在编译时会被转化成原子.举个例子,String别名默认转化成原子:"Elixir.String":

iex> is_atom(String)
true
iex> to_string(String)
"Elixir.String"
iex> :"Elixir.String" == String
true

使用alias/2命令,我们可以简单地修改别名要转化成的原子.

别名转化成原子是因为在Erlang虚拟机中模块总是用原子来代表.例如,这是我们调用Erlang模块的机制:

iex> :lists.flatten([1, [2], 3])
[1, 2, 3]

这也是我们之所以能动态地在一个模块中调用给定的函数:

iex> mod = :lists
:lists
iex> mod.flatten([1, [2], 3])
[1, 2, 3]

我们简单地使用原子:list调用了函数flatten.

#模块嵌套

我们已经讨论过了别名,现在我们可以讨论嵌套以及它在Elixir中的运作方式.思考下面的例子:

defmodule Foo do
  defmodule Bar do
  end
end

上述例子会定义两个模块:FooFoo.Bar.第二个可以被当做Bar里的Foo来访问,只要它们是在同一个语法空间里.上述代码等同于:

defmodule Elixir.Foo do
  defmodule Elixir.Foo.Bar do
  end
  alias Elixir.Foo.Bar, as: Bar
end

如果之后Bar模块在Foo的模块定义之外被调用,那就必须使用它的全名(Foo.Bar)或者别名.

注意:在Elixir中,你不必再定义Foo.Bar模块之前先定义Foo模块,因为语言会将所有模块名转化为原子.你可以定义任意嵌套的模块而不需要定义任何链条上的模块(例如:Foo.Bar.Baz不需先定义FooFoo.Bar).

下一章我们将看到,别名在宏中扮演了关键角色,保证了它们的清洁性.

#群体别名/进口/要求/使用

从Elixir v1.2开始,我们能同时给多个对象赋别名,进口或要求模块.当我们开始嵌套模块时,在构建Elixir应用时很常用,这会非常有用.例如,想象你有一个应用的所有模块都嵌套在MyApp之下,你可以同时为MyApp.Foo,MyApp.BarMyApp.Baz赋予别名:

alias MyApp.{Foo, Bar, Baz}

© 著作权归作者所有

共有 人打赏支持
ljzn
粉丝 29
博文 69
码字总数 96245
作品 0
南平
程序员
加载中

评论(2)

黄雄镖
黄雄镖
浓浓机翻味
o
ohoh_co
要求!进口!看到require和import惊了我一身尿
Elixir 学习资源

Elixir 官网 getting started官方入门学习资源 官方文档 hex 包管理系统 elixir sips 比较不错视频课程 Elixir China 中文论坛 官方wiki Elixir by Example Awesome Elixir Elixir Quiz 通过...

lidashuang
2017/11/29
0
0
elixir官方入门教程 介绍

介绍 安装 交互模式 运行脚本 提出疑问 欢迎! 在本教程中我们将教给你Elixir的基础,语法,如何定义模块,如何操作常用数据结构的特性等等.本章将确保Elixir安装好了,并且你能够成功运行Elixir的...

ljzn
2016/08/06
70
0
elixir官方教程Mix与OTP(一) Mix入门

Mix入门 我们的第一个项目 编辑项目 执行测试 环境 探索 在本教程中,我们将学习如何构建一个完整的Elixir应用,包括监督树,配置,测试等等. 这个应用的功能是分布式键值仓库.我们将把键值对安排...

ljzn
2016/08/07
1K
2
elixir官方教程 元编程(二) 宏

宏 前言 我们的第一个宏 宏的隔离 环境 私有宏 负责任地编写宏 前言 尽管Elixir已竭力为宏提供一个安全的环境,用宏编写干净代码的责任仍然落在了开发者身上.宏比传统的Elixir函数更难编写,而...

ljzn
2016/08/14
1K
3
elixir官方入门教程 学习资料

下一步该去哪 构建你的第一个Elixir项目 元编程 社区与其它资源 Erlang基础 想要学习更多?继续阅读! 构建你的第一个Elixir项目 为了开始你的第一个项目,Elixir装载了一个叫做Mix的构建工具....

ljzn
2016/08/06
144
0

没有更多内容

加载失败,请刷新页面

加载更多

虚拟机学习之二:垃圾收集器和内存分配策略

1.对象是否可回收 1.1引用计数算法 引用计数算法:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时候计数器值为0的对象就是不可能...

贾峰uk
11分钟前
0
0
smart-doc特殊功能使用介绍

smart-doc从8月份底开始开源发布到目前为止已经迭代了几个版本。在这里非常感谢那些敢于用smart-doc去做尝试并积极提出建议的社区用户。因此决定在本博客中重要说明下smart-doc的功能,包括使...

上官胡闹
昨天
1
0
JavaEE——Junit

声明:本栏目所使用的素材都是凯哥学堂VIP学员所写,学员有权匿名,对文章有最终解释权;凯哥学堂旨在促进VIP学员互相学习的基础上公开笔记。 Junit Junit又名单元测试,Junit是用来测试Jav...

凯哥学堂
昨天
1
0
读《美丽新世界》

一、背景 十一国庆节从重庆回深圳的时候,做得绿皮车,路上看了两本书:李笑来的《韭菜的自我修养》和禁书《美丽新世界》。 上篇文章已经分享了 读《韭菜的自我修养》,这篇文章来记录一下《...

tiankonguse
昨天
1
0
archlinux下基于Jenkins,docker实现自动化部署(持续交互)

本文永久更新地址:https://my.oschina.net/bysu/blog/2250954 【若要到岸,请摇船:开源中国 不最醉不龟归】 -----------------------------------第一部分Jenkins的安装与使用-----------...

不最醉不龟归
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部