自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

神奇的仙丹,性感的Elixir

開發(fā) 開發(fā)工具
在IT世界里,沒有銀彈,但卻有神奇的仙丹(Elixir)。我不知道是什么靈感刺激這門語言的創(chuàng)造者José Valim想到了這么酷的命名,但這枚仙丹確實(shí)經(jīng)由多種神奇的靈藥煉制而成,這些靈藥包括Erlang、Ruby、Clojure、Haskell。

在IT世界里,沒有銀彈,但卻有神奇的仙丹(Elixir)。我不知道是什么靈感刺激這門語言的創(chuàng)造者José Valim想到了這么酷的命名,但這枚仙丹確實(shí)經(jīng)由多種神奇的靈藥煉制而成,這些靈藥包括Erlang、Ruby、Clojure、Haskell。

品嘗這枚仙丹確實(shí)令人飄飄欲仙,至少,我在淺嘗Elixir時,這種奇妙的感覺一直縈繞在我心間,怦然心動因而不舍離去?;蛟S如Erlang之父Joe Armstrong所說,是“一種先行于邏輯的內(nèi)心感性的感覺”;又或者如Dave Thomas形容的,那是讓人“墜入愛河”的感覺。

大愛Elixir。

我之所以愛上Elixir,大約還是因?yàn)镽uby的緣故。我并非Ruby的狂熱追隨者,甚至沒有從事太多Ruby相關(guān)的項(xiàng)目,但我至今在編寫腳本時,Ruby依舊是我的首選。在動態(tài)語言中,我甚喜愛Ruby相對簡潔的語法。當(dāng)我看到Elixir時,那種似曾相識的感覺讓我心動。

雖然說Elixir的煉制來自各位前輩留下的丹方靈藥,然而從成丹之日起,Elixir就是Elixir,她已經(jīng)具有了完整的語言性格。就我看來,Elixir真正稱得上是“性感”。當(dāng)然,這一大半要?dú)w功于Erlang美麗的英倫風(fēng)情(Erlang之父Joe Armstrong是英國人),就Erlang的高顏值打底,只需再加上幾點(diǎn)嫵媚,幾分妖嬈,風(fēng)采就變得性感撩人了。

并發(fā)與分布式

Elixir對并發(fā)與分布式的支持,就是正宗的英倫風(fēng)情,這是從Erlang延續(xù)下來的最強(qiáng)悍基因。Elixir建立在Erlang虛擬機(jī)(BEAM)之上,使用Erlang的進(jìn)程,如原生進(jìn)程那樣在所有的處理器中運(yùn)行,然而開銷卻非常小。與Erlang一樣,Elixir可以通過spawn輕松地創(chuàng)建進(jìn)程:

  1. spawn fn -> 1 + 2 end 

Elixir或者說Erlang的進(jìn)程依靠消息傳遞完成通信。進(jìn)程接收到的消息實(shí)際上是獲取的一份消息副本,這就使得接收方能夠與發(fā)送方解耦,接收方對消息的任何操作不會影響接收方。

  1. send self, {:hello, "world"}receive do 
  2. {:hello, msg} -> msg 
  3. {:world, msg} -> "won't match" 
  4. end 

Elixir的核心繼承自Erlang,自然就繼承了對OTP(Open Telecom Platform)的支持。OTP是一個很大的課題,包括進(jìn)程鏈接、監(jiān)控以及分布式支持(我正在學(xué)習(xí)《Erlang/OTP并發(fā)編程實(shí)戰(zhàn)》,希望從Erlang根源上理解OTP)。Elixir對OTP的支持包括Agent、Task、GenServer以及Supervisor與Application。其中,Agent與Task是Elixir對OTP特性的抽象,而GenServer則更加通用。

在Elixir創(chuàng)建OTP服務(wù)器非常簡單,只需要use GenServer即可。它主要的方法為handle_call(request, from, state)與handle_cast(request, state)。如果客戶端發(fā)送的請求需要響應(yīng)時,則消息形式為call,如果為單向調(diào)用,則形式為cast。

考慮進(jìn)程的健壯性問題,在編寫OTP應(yīng)用時,可能還需要對進(jìn)程進(jìn)行監(jiān)督?;贏ctor模型,父進(jìn)程將負(fù)責(zé)監(jiān)督由其創(chuàng)建的所有子進(jìn)程,下面的代碼是Elixir官方提供的Supervisor代碼:

  1. defmodule KV.Supervisor do 
  2.   use Supervisor 
  3.  
  4.   def start_link do 
  5.     Supervisor.start_link(__MODULE__, :ok) 
  6.   end 
  7.  
  8.   def init(:ok) do 
  9.     children = [ 
  10.         worker(KV.Registry, [KV.Registry]), 
  11.         supervisor(KV.Bucket.Supervisor, []) 
  12.     ] 
  13.  
  14.     supervise(children, strategy: :rest_for_one) 
  15.   end 
  16. end 

KV.Supervisor為監(jiān)督進(jìn)程,其子進(jìn)程分別為KV.Registry與KV.Bucket.Supervisor,監(jiān)督策略為rest_for_one。

至于分布式支持,在Elixir其實(shí)是水到渠成的事情,因?yàn)樗暮诵氖沁M(jìn)程間通信,而進(jìn)程所在的節(jié)點(diǎn)位置,對于用戶而言是透明的。

模式匹配

模式匹配是Elixir最妖嬈的部分,雖然很多函數(shù)式語言都有模式匹配,但Elixir卻把模式匹配融入到其血肉之中(其實(shí)是延續(xù)了Erlang的模式匹配特色)。即使是一個賦值語句,也是模式匹配的一部分。在Elixir中,=符號其實(shí)被稱之為匹配運(yùn)算符(match operator)。所以你可以寫出違反程序員常規(guī)的1 = x:

  1. iex> 1 = x 
  2. iex> 2 = x 
  3. ** (MatchError) no match of right hand side value: 1 

模式匹配在Elixir中被廣泛地運(yùn)用到解構(gòu)(destructuring )復(fù)雜的數(shù)據(jù)結(jié)構(gòu),例如Tuple、List等。當(dāng)然case進(jìn)行的模式匹配更是它最常見的使用場景。

函數(shù)與模式匹配的結(jié)合才是體現(xiàn)妖嬈性的關(guān)鍵點(diǎn),如果再結(jié)合guard clause,那就真正讓人銷魂了。

大多數(shù)語言的函數(shù)定義是支持函數(shù)重載的,這取決于參數(shù)的類型、個數(shù)與順序。在動態(tài)語言中沒有類型,則與個數(shù)與順序相關(guān)。這些參數(shù)在定義時皆為形參(部分語言支持默認(rèn)參數(shù)值,Elixir也支持,甚至可以將表達(dá)式作為默認(rèn)參數(shù)),在調(diào)用時才傳入實(shí)參。

但是,Elixir則不然,因?yàn)镋lixir沒有賦值的概念,因此在傳遞參數(shù)時,并非賦值的語義,而是匹配的語義。因而出現(xiàn)如下的函數(shù)定義,你不要感到詫異哦:

  1. defmodule Factorial do 
  2.     def of(0), do: 1 
  3.     def of(n), do: n * of(n-1)  
  4. end 

在Elixir語義中,這兩個定義實(shí)則是同一個函數(shù),當(dāng)調(diào)用of函數(shù)時,傳入的參數(shù)會與第一個定義進(jìn)行匹配,如果匹配不成功,則匹配第二個定義。利用這種模式匹配,既可以規(guī)避實(shí)現(xiàn)上的if分支,又可以更好地體現(xiàn)遞歸的語義。

Meyer非常強(qiáng)調(diào)軟件開發(fā)中對“契約”的遵循,在他設(shè)計(jì)的語言Eiffel中,前置條件與后置條件作為了語法糖中的一等公民被支持。Erlang的guard Cluase與Eiffel的前置條件非常相似,Elixir也保留了這一語法特性。例如在前面的階乘算法中,我們可以通過guard clause避免傳入錯誤的負(fù)數(shù):

  1. defmodule Factorial do 
  2.     def of(0), do: 1 
  3.     def of(n) when n > 0, do: n * of(n-1) 
  4. end 

管道運(yùn)算符

讓Elixir展現(xiàn)其嫵媚一面的,是超級性感的管道運(yùn)算符。她讓整段代碼瞬間變得可愛起來。有了她,我們就不用再陷入可怕的函數(shù)嵌套地獄中了。Dave Long在博文Playing with Elixir Pipes中給出了一個頗有對照意義的例子。代碼功能是從conn取得Request的header,并判斷它是否有效。如果有效就返回conn,否則終止,并返回Not Authorized。

如果沒有管道運(yùn)算符,就得承受嵌套函數(shù)調(diào)用的驚悚感:

  1. signature = List.first(get_req_header(conn, "x-twilio-signature"))   
  2. is_valid = Validator.validate(url_from_conn(conn), conn.params, signature)   
  3. if is_valid do   
  4.   conn 
  5. else   
  6.   halt(send_resp(conn, 401, "Not authorized")) 
  7. end 

這樣的代碼完全違反人類直覺的,因?yàn)槟愕脧暮瘮?shù)最里邊閱讀,然后再層層往外逃逸。是否有一種被緊緊捆綁了的感覺呢?當(dāng)然,在很多語言中我們都無奈地接受了這一點(diǎn),已經(jīng)被虐得習(xí)以為常了。嘗試一下管道運(yùn)算符,會怎么樣?

  1. signature = conn   
  2.             |> get_req_header("x-twilio-signature"
  3.             |> List.first 
  4. if conn   
  5.    |> url_from_conn 
  6.    |> Validator.validate(conn.params, signature) 
  7. do   
  8.   conn 
  9. else   
  10.   conn |> send_resp(401, "Not authorized") |> halt 
  11. end 

當(dāng)你把管道運(yùn)算符|>看成是goto的話,我們就能直觀地體會到conn在各個函數(shù)中流動的現(xiàn)象了。非??蓯?,不是嗎?

Elixir是純正的函數(shù)式語言,本質(zhì)上講,Elixir中的一切皆為函數(shù),所以if表達(dá)式其實(shí)也是函數(shù)。這就意味著validate后的布爾結(jié)果可以通過|>直接傳遞給if:

  1. signature = conn   
  2.             |> get_req_header("x-twilio-signature"
  3.             |> List.first 
  4. conn   
  5. |> url_from_conn 
  6. |> Validator.validate(conn.params, signature) 
  7. |> if(do: conn, else: conn |> send_resp(401, "Not authorized") |> halt) 

這才是真正Elixir Style的編程范兒,夠嫵媚吧!

Joe Armstrong認(rèn)為管道運(yùn)算符來自Prolog語言的隱性基因DCG,類似Haskell中的monad。Prolog的兒子erlang沒有體現(xiàn)這一點(diǎn),孫子輩又隔代遺傳上了。

工程支持

Elixir的創(chuàng)造者José Valim乃Rails的核心參與者,所以他把Rails社區(qū)(包括Ruby社區(qū))中一套讓人目眩的工程實(shí)踐照般過來了。

腳手架

通過mix可以直接幫助我們創(chuàng)建項(xiàng)目的腳手架(用過rails的童鞋感到親切了嗎?):

mix new myproject

執(zhí)行這條命令,mix就會幫我們創(chuàng)建項(xiàng)目的基本結(jié)構(gòu)和相應(yīng)文件:

包管理與依賴管理

通過Hex來管理包(記得GEM嗎?)。在http://hex.pm中幾乎可以找到所有你想要的elixir包;當(dāng)然你還可以享受Erlang的福利,直接重用erlang包。

添加依賴也非常方便,只需要在項(xiàng)目的mix.exs文件中添加依賴即可。例如添加HTTPoison和JSX包的依賴:

  1. defp deps do 
  2.    [ 
  3.      {:httpoison, "~> 0.11.0"}, 
  4.      {:jsx, "~> 2.8"
  5.    ] 
  6.  end 

最棒的是,Elixir還支持直接對github repository的依賴。

環(huán)境配置

對開發(fā)環(huán)境、測試環(huán)境、生產(chǎn)環(huán)境的配置支持。在config目錄下的config.exs文件中可以添加必要的配置項(xiàng),還可以通過如下語句import不同環(huán)境的配置:

  1. import_config "#{Mix.env}.exs" 

單元測試

還有不能忘記的單元測試,這可是敏捷社區(qū)的隨身法寶啊;Elixir通過內(nèi)嵌的ExUnit很好地支持了單元測試的編寫:

  1. defmodule MyprojectTest do 
  2.   use ExUnit.Case 
  3.   doctest Myproject 
  4.  
  5.   test "sort ascending orders the correct way" do 
  6.     result = sort_into_ascending_order(fake_created_at_list(["c""a""b"])) 
  7.     issues = for issue <- result, do: issue["created_at"
  8.     assert issues == ~w{a b c} 
  9.   end 
  10. end 

如此簡單。要運(yùn)行所有測試,只需運(yùn)行mix test即可。

其他

Elixir還有很多酷炫的玩意兒,例如Protocol、Behavior,當(dāng)然還有最棒的(當(dāng)然也可能是最令人費(fèi)解的)宏(Macro)。Elixir對DSL的支持也非常友好,這來自它繼承的部分Ruby血統(tǒng)。例如,讓我們看看ECTO(一個基于Elixir開發(fā)的支持?jǐn)?shù)據(jù)庫訪問的框架)的一段客戶代碼:

  1. defmodule Sample.App do 
  2.   import Ecto.Query 
  3.   alias Sample.Weather 
  4.   alias Sample.Repo 
  5.  
  6.   def keyword_query do 
  7.     query = from w in Weather, 
  8.          where: w.prcp > 0 or is_nil(w.prcp), 
  9.          select: w 
  10.     Repo.all(query) 
  11.   end 
  12.  
  13.   def pipe_query do 
  14.     Weather 
  15.     |> where(city: "Kraków"
  16.     |> order_by(:temp_lo) 
  17.     |> limit(10) 
  18.     |> Repo.all 
  19.   end 
  20. end 

因?yàn)闆]有大括號、括號以及分號的干擾,代碼可以變得更接近領(lǐng)域邏輯,再加上性感的管道運(yùn)算符,可讀性直接爆表,帥呆了!

【本文為51CTO專欄作者“張逸”原創(chuàng)稿件,轉(zhuǎn)載請聯(lián)系原作者】

戳這里,看該作者更多好文

責(zé)任編輯:武曉燕 來源: 51CTO專欄
相關(guān)推薦

2015-11-02 17:25:23

Elixir編程語言未來

2013-06-09 10:51:35

2012-08-31 09:53:44

Noa TishbyMinit

2011-06-01 09:49:55

程序員IT

2023-04-18 08:14:27

ElixirRustWebRTC

2012-08-13 09:25:13

Windows 8操作系統(tǒng)

2020-06-08 07:52:31

Python開發(fā)工具

2012-08-24 10:49:51

備份恢復(fù)

2013-05-17 09:00:07

云計(jì)算云應(yīng)用云安全

2020-08-29 19:29:09

Pythonturtle

2009-08-27 17:47:21

c#皮膚

2012-10-09 13:41:09

數(shù)據(jù)科學(xué)家職業(yè)

2018-05-02 16:23:24

中間件RPC容器

2023-10-13 13:19:02

Java枚舉

2013-11-05 09:26:19

Mavericks系統(tǒng)OS X

2020-10-26 19:19:09

緩存Redis場景

2017-04-05 11:10:23

Javascript代碼前端

2021-10-08 21:00:52

數(shù)據(jù)弱引用對象

2009-11-06 18:56:22

Windows 7任務(wù)欄

2021-12-03 06:02:19

CSS濾鏡前端
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號