神奇的仙丹,性感的Elixir

在IT世界里,没有银弹,但却有神奇的仙丹(Elixir)。我不知道是什么灵感刺激这门语言的创造者José Valim想到了这么酷的命名,但这枚仙丹确实经由多种神奇的灵药炼制而成,这些灵药包括Erlang、Ruby、Clojure、Haskell。
品尝这枚仙丹确实令人飘飘欲仙,至少,我在浅尝Elixir时,这种奇妙的感觉一直萦绕在我心间,怦然心动因而不舍离去。或许如Erlang之父Joe Armstrong所说,是“一种先行于逻辑的内心感性的感觉”;又或者如Dave Thomas形容的,那是让人“坠入爱河”的感觉。
大爱Elixir。
我之所以爱上Elixir,大约还是因为Ruby的缘故。我并非Ruby的狂热追随者,甚至没有从事太多Ruby相关的项目,但我至今在编写脚本时,Ruby依旧是我的首选。在动态语言中,我甚喜爱Ruby相对简洁的语法。当我看到Elixir时,那种似曾相识的感觉让我心动。
虽然说Elixir的炼制来自各位前辈留下的丹方灵药,然而从成丹之日起,Elixir就是Elixir,她已经具有了完整的语言性格。就我看来,Elixir真正称得上是“性感”。当然,这一大半要归功于Erlang美丽的英伦风情(Erlang之父Joe Armstrong是英国人),就Erlang的高颜值打底,只需再加上几点妩媚,几分妖娆,风采就变得性感撩人了。
并发与分布式
Elixir对并发与分布式的支持,就是正宗的英伦风情,这是从Erlang延续下来的最强悍基因。Elixir建立在Erlang虚拟机(BEAM)之上,使用Erlang的进程,如原生进程那样在所有的处理器中运行,然而开销却非常小。与Erlang一样,Elixir可以通过spawn轻松地创建进程:
spawn fn -> 1 + 2 end
Elixir或者说Erlang的进程依靠消息传递完成通信。进程接收到的消息实际上是获取的一份消息副本,这就使得接收方能够与发送方解耦,接收方对消息的任何操作不会影响接收方。
send self, {:hello, "world"}receive do{:hello, msg} -> msg{:world, msg} -> "won't match"
end
Elixir的核心继承自Erlang,自然就继承了对OTP(Open Telecom Platform)的支持。OTP是一个很大的课题,包括进程链接、监控以及分布式支持(我正在学习《Erlang/OTP并发编程实战》,希望从Erlang根源上理解OTP)。Elixir对OTP的支持包括Agent、Task、GenServer以及Supervisor与Application。其中,Agent与Task是Elixir对OTP特性的抽象,而GenServer则更加通用。
在Elixir创建OTP服务器非常简单,只需要use GenServer即可。它主要的方法为handle_call(request, from, state)与handle_cast(request, state)。如果客户端发送的请求需要响应时,则消息形式为call,如果为单向调用,则形式为cast。
考虑进程的健壮性问题,在编写OTP应用时,可能还需要对进程进行监督。基于Actor模型,父进程将负责监督由其创建的所有子进程,下面的代码是Elixir官方提供的Supervisor代码:
defmodule KV.Supervisor douse Supervisordef start_link doSupervisor.start_link(__MODULE__, :ok)enddef init(:ok) dochildren = [worker(KV.Registry, [KV.Registry]),supervisor(KV.Bucket.Supervisor, [])]supervise(children, strategy: :rest_for_one)end
end
KV.Supervisor为监督进程,其子进程分别为KV.Registry与KV.Bucket.Supervisor,监督策略为rest_for_one。
至于分布式支持,在Elixir其实是水到渠成的事情,因为它的核心是进程间通信,而进程所在的节点位置,对于用户而言是透明的。
模式匹配
模式匹配是Elixir最妖娆的部分,虽然很多函数式语言都有模式匹配,但Elixir却把模式匹配融入到其血肉之中(其实是延续了Erlang的模式匹配特色)。即使是一个赋值语句,也是模式匹配的一部分。在Elixir中,=符号其实被称之为匹配运算符(match operator)。所以你可以写出违反程序员常规的1 = x:
iex> 1 = x
1
iex> 2 = x
** (MatchError) no match of right hand side value: 1
模式匹配在Elixir中被广泛地运用到解构(destructuring )复杂的数据结构,例如Tuple、List等。当然case进行的模式匹配更是它最常见的使用场景。
函数与模式匹配的结合才是体现妖娆性的关键点,如果再结合guard clause,那就真正让人销魂了。
大多数语言的函数定义是支持函数重载的,这取决于参数的类型、个数与顺序。在动态语言中没有类型,则与个数与顺序相关。这些参数在定义时皆为形参(部分语言支持默认参数值,Elixir也支持,甚至可以将表达式作为默认参数),在调用时才传入实参。
但是,Elixir则不然,因为Elixir没有赋值的概念,因此在传递参数时,并非赋值的语义,而是匹配的语义。因而出现如下的函数定义,你不要感到诧异哦:
defmodule Factorial dodef of(0), do: 1def of(n), do: n * of(n-1)
end
在Elixir语义中,这两个定义实则是同一个函数,当调用of函数时,传入的参数会与第一个定义进行匹配,如果匹配不成功,则匹配第二个定义。利用这种模式匹配,既可以规避实现上的if分支,又可以更好地体现递归的语义。
Meyer非常强调软件开发中对“契约”的遵循,在他设计的语言Eiffel中,前置条件与后置条件作为了语法糖中的一等公民被支持。Erlang的guard Cluase与Eiffel的前置条件非常相似,Elixir也保留了这一语法特性。例如在前面的阶乘算法中,我们可以通过guard clause避免传入错误的负数:
defmodule Factorial dodef of(0), do: 1def of(n) when n > 0, do: n * of(n-1)
end
管道运算符
让Elixir展现其妩媚一面的,是超级性感的管道运算符。她让整段代码瞬间变得可爱起来。有了她,我们就不用再陷入可怕的函数嵌套地狱中了。Dave Long在博文Playing with Elixir Pipes中给出了一个颇有对照意义的例子。代码功能是从conn取得Request的header,并判断它是否有效。如果有效就返回conn,否则终止,并返回Not Authorized。
如果没有管道运算符,就得承受嵌套函数调用的惊悚感:
signature = List.first(get_req_header(conn, "x-twilio-signature"))
is_valid = Validator.validate(url_from_conn(conn), conn.params, signature)
if is_valid do conn
else halt(send_resp(conn, 401, "Not authorized"))
end
这样的代码完全违反人类直觉,因为你得从函数最里边阅读,然后再层层往外逃逸。是否有一种被紧紧捆绑了的感觉呢?当然,在很多语言中我们都无奈地接受了这一点,已经被虐得习以为常了。尝试一下管道运算符,会怎么样?
signature = conn |> get_req_header("x-twilio-signature")|> List.first
if conn |> url_from_conn|> Validator.validate(conn.params, signature)
do conn
else conn |> send_resp(401, "Not authorized") |> halt
end
当你把管道运算符|>看成是goto的话,我们就能直观地体会到conn在各个函数中流动的现象了。非常可爱,不是吗?
Elixir是纯正的函数式语言,本质上讲,Elixir中的一切皆为函数,所以if表达式其实也是函数。这就意味着validate后的布尔结果可以通过|>直接传递给if:
signature = conn |> get_req_header("x-twilio-signature")|> List.first
conn
|> url_from_conn
|> Validator.validate(conn.params, signature)
|> if(do: conn, else: conn |> send_resp(401, "Not authorized") |> halt)
这才是真正Elixir Style的编程范儿,够妩媚吧!
Joe Armstrong认为管道运算符来自Prolog语言的隐性基因DCG,类似Haskell中的monad。Prolog的儿子erlang没有体现这一点,孙子辈又隔代遗传上了。
工程支持
Elixir的创造者José Valim乃Rails的核心参与者,所以他把Rails社区(包括Ruby社区)中一套让人目眩的工程实践照般过来了。
脚手架
通过mix可以直接帮助我们创建项目的脚手架(用过rails的童鞋感到亲切了吗?):
mix new myproject
执行这条命令,mix就会帮我们创建项目的基本结构和相应文件:

包管理与依赖管理
通过Hex来管理包(记得GEM吗?)。在http://hex.pm中几乎可以找到所有你想要的elixir包;当然你还可以享受Erlang的福利,直接重用erlang包。
添加依赖也非常方便,只需要在项目的mix.exs文件中添加依赖即可。例如添加HTTPoison和JSX包的依赖:
defp deps do[{:httpoison, "~> 0.11.0"},{:jsx, "~> 2.8"}]end
最棒的是,Elixir还支持直接对github repository的依赖。
环境配置
对开发环境、测试环境、生产环境的配置支持。在config目录下的config.exs文件中可以添加必要的配置项,还可以通过如下语句import不同环境的配置:
import_config "#{Mix.env}.exs"
单元测试
还有不能忘记的单元测试,这可是敏捷社区的随身法宝啊;Elixir通过内嵌的ExUnit很好地支持了单元测试的编写:
defmodule MyprojectTest douse ExUnit.Casedoctest Myprojecttest "sort ascending orders the correct way" doresult = sort_into_ascending_order(fake_created_at_list(["c", "a", "b"]))issues = for issue <- result, do: issue["created_at"]assert issues == ~w{a b c}end
end
如此简单。要运行所有测试,只需运行mix test即可。
其他
Elixir还有很多酷炫的玩意儿,例如Protocol、Behavior,当然还有最棒的(当然也可能是最令人费解的)宏(Macro)。Elixir对DSL的支持也非常友好,这来自它继承的部分Ruby血统。例如,让我们看看ECTO(一个基于Elixir开发的支持数据库访问的框架)的一段客户代码:
defmodule Sample.App doimport Ecto.Queryalias Sample.Weatheralias Sample.Repodef keyword_query doquery = from w in Weather,where: w.prcp > 0 or is_nil(w.prcp),select: wRepo.all(query)enddef pipe_query doWeather|> where(city: "Kraków")|> order_by(:temp_lo)|> limit(10)|> Repo.allend
end
因为没有大括号、括号以及分号的干扰,代码可以变得更接近领域逻辑,再加上性感的管道运算符,可读性直接爆表,帅呆了!
神奇的仙丹,性感的Elixir相关推荐
- 《Elixir in Action》书评及作者问答录
<Elixir in Action>是由Manning所出版的一本新书,本书为读者介绍了Elixir这门语言以及Erlang虚拟机,同时也讨论了与并发编程.容错以及与高可用性相关的话题.I ...
- [elixir! #0023] 引擎盖下, `IO.puts` 如何运作
`IO.puts "Hello world!" 接触elixir时, 学会的第一行代码是 IO.puts "Hello world!". 出于好奇, 我观察了一 ...
- Sublime Text 2 - 性感无比的代码编辑器!程序员必备神器!跨平台支持Win/Mac/Linux,支持32与64位,支持各种流行编程语言的语法高亮、代码补全等...
Sublime Text 2 - 性感无比的代码编辑器!程序员必备神器!跨平台支持Win/Mac/Linux,支持32与64位,支持各种流行编程语言的语法高亮.代码补全等-- 语法高亮.代码提示补全. ...
- 干翻华为才有年终奖,“性感”小米发布MIX3,滑盖全面屏只要3299元
Are you ok? 小米又发新机了! 这次发布会开到故宫了.虽然不知道故宫的花花草草和皇家御喵是不是米粉,但是正戏开始前还是先来一遍Are you ok清新洗脑一下吧! 话不多说,先前在8月份和O ...
- 90后创业者自述:不性感没逼格不能活
90后创业者自述:性爱不是说说而是做,不性感没逼格不能活 文/崔大宝 [本文来自钛媒体特色栏目"创业者自述",自述成长的故事] 现如今90后创业也是屡见不鲜的事情,而真正能够成功的 ...
- 机器人二弟_“可佳二代”机器人好性感
将本文分享到微博: 小观众认真观看机器人表演 "晨报读者这边走--"5月14日上午,在科大科技周各科普点,300余人的晨报"科技周"探秘团,在各分队志愿者导游带 ...
- Sublime Text 2 - 性感无比的代码编辑器
Address: http://www.iplaysoft.com/sublimetext.html Sublime Text 2 - 性感无比的代码编辑器!程序员必备神器!跨平台支持Win/Mac/ ...
- Lua sublime Text 2 - 性感无比的代码编辑器!程序员必备神器!跨平台支持Win/Mac/Linux
sublime Text 2 - 性感无比的代码编辑器!程序员必备神器!跨平台支持Win/Mac/Linux [ 编程开发, 编辑输入 - Windows, Mac, Linux // 20 ...
- 一段神奇的c代码错误分析
源代码 #include <stdio.h>int main(int argc, char* argv[]) {int i = 0;int arr[3] = {0};printf(&quo ...
最新文章
- Confluence 6 有关空间的一些提示
- GPIO 输入—按键检测
- 破windows xp登陆密码
- 好听的歌曲---爱情转移
- SpringBoot整合Spring Security——登录管理
- Serializable接口中serialVersionUID字段的作用
- docker实战系列之搭建rabbitmq
- python 什么是序列_从零起步学Python——什么是序列?
- yield关键字有什么作用
- jQuery之.queue()
- 洛谷省选斗兽场全通关祭~以及之后的打算!
- android datepicker 监听,Android编程之DatePicker和TimePicke简单时间监听用法分析
- excel编写计算机台账,[一键生成excel表格]excel表格生成台账的方法
- 超市密码箱c语言程序,超市存包系统C语言.doc
- UItraEdit激活码
- China Joy 还没看够?2020 谷歌游戏出海峰会带来更多精彩!
- word怎么根据点画曲线_用word怎么画曲线图 word里如何绘制曲线图
- gitbook安装使用看完这一篇就够了
- 如何优化我的世界服务器,我的世界服务器怎么优化 服务器优化建议
- PHPExcel大文件导入数据库
热门文章
- linux没有c编译器,兄弟们,我这有台电脑里的Linux缺少cc(C编译器),我该怎么把它补上去啊?急啊!!!...
- 广义表头尾链表存储结构_详解Redis五种数据结构的底层原理
- oracle中累计求和_Excel中常见的7种求和公式
- Linux截图工具import使用说明
- 斯坦福2019强化学习课程完结,讲义、PPT、视频已提供下载
- 无人车创业正驶入分水岭
- 又一北大系AI公司浮出水面,百炼智能宣布获千万元天使投资
- 马库斯再谈AlphaGo Zero不是从零开始,AGI可能需要这十大先天机制
- 李开复:2018中国最大AI红利?是政策
- 当区块链遇到零知识证明 1