文档章节

elixir官方教程 元编程(一) 引用与去引用

ljzn
 ljzn
发布于 2016/08/13 21:10
字数 1352
阅读 52
收藏 0
点赞 0
评论 0

#引用与去引用

  1. 引用(Quoting)
  2. 去引用(Unquoting)
  3. 释放(Escaping)

一个Elixir程序可以用它自己的数据结构来表现.本章,我们将会学习这些结构体的特点和如何组成它们.本章我们要学习的概念是为宏的积木(building blocks),在下一章中我们将深入研究它.

#引用(Quoting)

Elixir程序中的积木是一个三元素元组.例如,函数sum(1, 2, 3)的内部表示是:

{:sum, [], [1, 2, 3]}

你可以用quote宏来得到任何表达式的内部表现:

iex> quote do: sum(1, 2, 3)
{:sum, [], [1, 2, 3]}

第一个元素是函数名,第二个元素是一个包含了元数据的关键词列表,第三个元素是参数列表.

操作符也可以用元组来表示:

iex> quote do: 1 + 2
{:+, [context: Elixir, import: Kernel], [1, 2]}

甚至一个映射都被表示成对%{}的调用:

iex> quote do: %{1 => 2}
{:%{}, [], [{1, 2}]}

变量也能这样三段式表示,只不过最后的元素换成了一个原子:

iex> quote do: x
{:x, [], Elixir}

当引用更复杂的表达式时,代码被表示成了一个树状的嵌套元组.许多语言将这种表示称为抽象语法树(AST).ELixir称其为引用表达式:

iex> quote do: sum(1, 2 + 3, 4)
{:sum, [], [1, {:+, [context: Elixir, import: Kernel], [2, 3]}, 4]}

有时,把引用表达式还原为文本代码会很有用.可以用Macro.to_string/1来完成:

iex> Macro.to_string(quote do: sum(1, 2 + 3, 4))
"sum(1, 2 + 3, 4)"

通常,上述元组的结构会是这种格式:

{atom | tuple, list, list | atom}

- 第一个元素是一个原子,或者是同样表达方式的另一个元组; - 第二个元素是一个关键词列表,包含元数据,比如数字和语境; - 第三个元素是函数调用的参数列表或者是一个原子.当为原子时,意味着元组表示的是一个变量.

除了上面定义的元组,有五个Elixir字面量,在被引用时,会返回它们自己(而不是一个元组).它们是:

:sum         #=> Atoms
1.0          #=> Numbers
[1, 2]       #=> Lists
"strings"    #=> Strings
{key, value} #=> Tuples with two elements

大多数Elixir代码都有一个直截了当的引用表达式.我们建议你尝试不同的代码,看看结果如何.比如,String.upcase("foo")会如何展开?我们已经知道if(true, do: :this, else: :that)等同于if true do :this else :that end.它要如何用引用表达式来容纳?

#去引用(Unquoting)

引用可以获得一些特定代码块的内部表达式.然而,有时我们需要注入一些特定代码块到我们想要获取的表达式中.

例如,假设我们有一个变量,包含了我们想注入一个引用表达式中的数字,变量名为number.

iex> number = 13
iex> Macro.to_string(quote do: 11 + number)
"11 + number"

那不是我们想要的,number变量被引入了表达式,但number变量的值没有被注入.为了注入number变量的值,我们需要在引用表达式中使用unquote:

iex> number = 13
iex> Macro.to_string(quote do: 11 + unquote(number))
"11 + 13"

unquote甚至可以被用于注入函数名:

iex> fun = :hello
iex> Macro.to_string(quote do: unquote(fun)(:world))
"hello(:world)"

在相同的情况下,可能需要注入一个有许多值的列表.比如,假设你有一个列表[1, 2, 6],我们想把[3, 4, 5]注入进去.使用unquote却不能得到想要的结果:

iex> inner = [3, 4, 5]
iex> Macro.to_string(quote do: [1, 2, unquote(inner), 6])
"[1, 2, [3, 4, 5], 6]"

这时就轮到unquote_splicing出场了:

iex> inner = [3, 4, 5]
iex> Macro.to_string(quote do: [1, 2, unquote_splicing(inner), 6])
"[1, 2, 3, 4, 5, 6]"

去引用在操作宏的时候很有用.编写宏的时候,开发者可以获取代码块并将它们注入到其它代码块中,这可以被用于改变代码或者编写能在编译时生成代码的代码.

#释放(Escaping)

如本章开头所见,Elixir中只有一部分值有合法的引用表达式.比如,一个映射没有合法的引用表达式.四元素的元组也没有.然而,这些值可以被表示成一个引用表达式:

iex> quote do: %{1 => 2}
{:%{}, [], [{1, 2}]}

有时你需要将这种值注入引用表达式中.我们首先需要将这些值释放到引用表达式中,使用Macro.escape/1来完成:

iex> map = %{hello: :world}
iex> Macro.escape(map)
{:%{}, [], [hello: :world]}

宏接收引用表达式,并必须返回引用表达式.然而执行宏的过程中,你可能需要处理一些值,并且区分值与引用表达式.

也就是说,区分常规的Elixir值(例如列表,映射,进程,参考等等)与引用表达式,是很重要的.有一些值的引用表达式就是它们自己,例如整数,原子核字符串.另一些值,比如映射,需要被显式转换.最后,函数与参考完全不能被转化成引用表达式.

你可以在Kernel.SpecialForms模块中阅读更多关于quoteunquote的内容.在Macro模块中可以找到Macro.escape/1的文档和其它与引用表达式相关的函数.

在本教程中我们将编写自己的第一个宏,让我们进入下一章吧.

© 著作权归作者所有

共有 人打赏支持
ljzn
粉丝 29
博文 69
码字总数 96245
作品 0
南平
程序员
elixir官方教程 元编程(二) 宏

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

ljzn ⋅ 2016/08/14 ⋅ 3

elixir官方入门教程 学习资料

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

ljzn ⋅ 2016/08/06 ⋅ 0

Elixir学习笔记(模型匹配、控制语句)

模型匹配 模式匹配是 Elixir 很强大的特性,它允许我们匹配简单值、数据结构、甚至函数。 匹配运算符 在Elixir中,运算符实际上叫做 匹配运算符。通过这个匹配操作符,我们可以赋值和匹配值。...

程序员小哥哥 ⋅ 04/12 ⋅ 0

Elixir 学习资源

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

lidashuang ⋅ 2017/11/29 ⋅ 0

Elixir: 编程语言的未来

这篇文章谈一谈最近火爆的 Elixir,同时说一下对编程语言选择的看法。同时作为 Erlang 发烧友,Elixir 不可不提。即使有了那么多编程语言 Elixir 也值得接触。 现在开始接触 Elixir 对编程语...

oschina ⋅ 2015/08/02 ⋅ 18

总有你要的编程书单(GitHub )

目录 IDE IntelliJ IDEA 简体中文专题教程 MySQL 21分钟MySQL入门教程 MySQL索引背后的数据结构及算法原理 NoSQL Disque 使用教程 Neo4j .rb 中文資源 Redis 命令参考 Redis 设计与实现 The ...

汇智网 ⋅ 2017/11/22 ⋅ 0

elixir官方入门教程 模块

模块 编译 脚本模式 具名函数 函数捕获 默认参数 在Elixir中我们将一些函数集合到模块里。在之前的章节里我们已经使用了许多不同的模块,例如模块: 为了创造我们自己的模块,需要用到宏。我...

ljzn ⋅ 2016/08/03 ⋅ 0

elixir官方入门教程 类型规格与行为

类型规格与行为 类型与规格 函数规格 自定义类型 静态代码分析 行为 定义行为 采用行为 类型与规格 Elixir是一门动态类型语言,所以Elixir中的所有类型都会在运行时被判定.尽管如此,Elixir拥有...

ljzn ⋅ 2016/08/06 ⋅ 0

elixir官方教程 元编程(三) 领域特定语言

领域特定语言 前言 构建我们的测试案例 宏 用属性存储信息 前言 领域特定语言(DSL)允许开发者修改他们的应用以适应特定的领域.制作DSL可以不需要用到宏:你在你的模块中定义的每个数据结构和每...

ljzn ⋅ 2016/08/14 ⋅ 0

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

别名,要求与进口 别名 要求 进口 使用 理解别名 模块嵌套 群体别名/进口/要求/使用 为了方便软件复用,Elixir提供了三个命令(,和)外加一个宏,简介如下: 现在我们将详细探索它们.记住前三条之所...

ljzn ⋅ 2016/08/04 ⋅ 2

没有更多内容

加载失败,请刷新页面

加载更多

下一页

AppDelegate 设置Root相关

self.window = UIWindow.init(frame: UIScreen.main.bounds) self.window?.backgroundColor = UIColor.white self.window?.makeKeyAndVisible() self.window?.rootViewController = RootTabB......

west_zll ⋅ 9分钟前 ⋅ 0

Java并发系列5--倒计时器CountDownLatch

今天讲一个倒计时器工具,叫CountDownLatch。需要这个工具的场景大概有:当所有的小任务都完成之后,再启动大任务。 先看代码: public class CountDownLatchDemo {static final CountDow...

大大枣 ⋅ 11分钟前 ⋅ 0

SpreadJS使用进阶指南 - 使用 NPM 管理你的项目

前言 SpreadJS作为一款性能出众的纯前端电子表格控件,自2015年发布以来,已经被广泛应用于各领域“在线Excel”数据管理项目中。NPM,作为管理Node.js库最有力的手段,解决了很多NodeJS代码部...

葡萄城控件技术团队 ⋅ 12分钟前 ⋅ 0

Mac下IntelliJ IDEA快捷键大全

https://blog.csdn.net/lisongjia123/article/details/54949364

细节探索者 ⋅ 15分钟前 ⋅ 0

建造者模式

1、工厂模式中创建的对象大都是简单的对象 复杂的产品类并且拥有不同的属性特点的管理就需要用到建造者模式 2、建造者模式: 将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以...

职业搬砖20年 ⋅ 16分钟前 ⋅ 0

Mysql数据库开发 怎么优化SQL语句?

 1) 现场抓出慢查询语句 show full processlist;   2) 配置参数:   slow_query_log_file = ON 慢查询开启开关   long_query_time =2 记录大于2秒的sql语句   log_queries_not_usi...

老男孩Linux培训 ⋅ 16分钟前 ⋅ 0

Laravel 安装执行php artisan migrate 出现字段过长错误

最近在自己研究Laravel Laravel版本:5.6 PHP版本:7.1.9 Mysql版本:5.7.19 Apache版本:2.4.27 系统版本:windows10 首先要保证电脑安装了composer,和node.js 执行命令 composer global ...

Marhal ⋅ 22分钟前 ⋅ 0

ELK6.0日志从收集到处理完整版教程(二)

ELK简介 Elasticsearch 开源分布式搜索引擎,它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,restful风格接口,多数据源,自动搜索负载等。也可以认为ElasticSearch是一...

bz_z ⋅ 24分钟前 ⋅ 0

Spark项目之电商用户行为分析大数据平台之(七)数据调研--基本数据结构介绍

目录 一、user_visit_action(Hive表) 1.1 表的结构 1.2 表的说明 二、user_info(Hive表) 2.1 表的结构 2.2 表的说明 三、task(MySQL表) 3.1 表的结构 3.2 表的说明 四、工作流程...

xiaomin0322 ⋅ 29分钟前 ⋅ 0

评分卡模型剖析之一(woe、IV、ROC、信息熵)

信用评分卡模型在国外是一种成熟的预测方法,尤其在信用风险评估以及金融风险控制领域更是得到了比较广泛的使用,其原理是将模型变量WOE编码方式离散化之后运用logistic回归模型进行的一种二...

火力全開 ⋅ 30分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部