成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

神奇的仙丹,性感的Elixir

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

在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輕松地創建進程:

  1. spawn fn -> 1 + 2 end 

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

  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是一個很大的課題,包括進程鏈接、監控以及分布式支持(我正在學習《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應用時,可能還需要對進程進行監督?;贏ctor模型,父進程將負責監督由其創建的所有子進程,下面的代碼是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為監督進程,其子進程分別為KV.Registry與KV.Bucket.Supervisor,監督策略為rest_for_one。

至于分布式支持,在Elixir其實是水到渠成的事情,因為它的核心是進程間通信,而進程所在的節點位置,對于用戶而言是透明的。

模式匹配

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

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

模式匹配在Elixir中被廣泛地運用到解構(destructuring )復雜的數據結構,例如Tuple、List等。當然case進行的模式匹配更是它最常見的使用場景。

函數與模式匹配的結合才是體現妖嬈性的關鍵點,如果再結合guard clause,那就真正讓人銷魂了。

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

但是,Elixir則不然,因為Elixir沒有賦值的概念,因此在傳遞參數時,并非賦值的語義,而是匹配的語義。因而出現如下的函數定義,你不要感到詫異哦:

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

在Elixir語義中,這兩個定義實則是同一個函數,當調用of函數時,傳入的參數會與第一個定義進行匹配,如果匹配不成功,則匹配第二個定義。利用這種模式匹配,既可以規避實現上的if分支,又可以更好地體現遞歸的語義。

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

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

管道運算符

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

如果沒有管道運算符,就得承受嵌套函數調用的驚悚感:

  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 

這樣的代碼完全違反人類直覺的,因為你得從函數最里邊閱讀,然后再層層往外逃逸。是否有一種被緊緊捆綁了的感覺呢?當然,在很多語言中我們都無奈地接受了這一點,已經被虐得習以為常了。嘗試一下管道運算符,會怎么樣?

  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 

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

Elixir是純正的函數式語言,本質上講,Elixir中的一切皆為函數,所以if表達式其實也是函數。這就意味著validate后的布爾結果可以通過|>直接傳遞給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認為管道運算符來自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包的依賴:

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

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

環境配置

對開發環境、測試環境、生產環境的配置支持。在config目錄下的config.exs文件中可以添加必要的配置項,還可以通過如下語句import不同環境的配置:

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

單元測試

還有不能忘記的單元測試,這可是敏捷社區的隨身法寶啊;Elixir通過內嵌的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 

如此簡單。要運行所有測試,只需運行mix test即可。

其他

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

  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 

因為沒有大括號、括號以及分號的干擾,代碼可以變得更接近領域邏輯,再加上性感的管道運算符,可讀性直接爆表,帥呆了!

【本文為51CTO專欄作者“張逸”原創稿件,轉載請聯系原作者】

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

責任編輯:武曉燕 來源: 51CTO專欄
相關推薦

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

2012-08-13 09:25:13

Windows 8操作系統

2023-04-18 08:14:27

ElixirRustWebRTC

2020-06-08 07:52:31

Python開發工具

2012-08-24 10:49:51

備份恢復

2009-08-27 17:47:21

c#皮膚

2013-05-17 09:00:07

云計算云應用云安全

2020-08-29 19:29:09

Pythonturtle

2012-10-09 13:41:09

數據科學家職業

2013-11-05 09:26:19

Mavericks系統OS X

2021-10-08 21:00:52

數據弱引用對象

2020-10-26 19:19:09

緩存Redis場景

2017-04-05 11:10:23

Javascript代碼前端

2009-11-06 18:56:22

Windows 7任務欄

2023-10-13 13:19:02

Java枚舉

2018-05-02 16:23:24

中間件RPC容器

2020-02-10 14:26:10

GitHub代碼倉庫
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美成视频| 亚洲国产成人精品女人久久久野战 | 天天色官网 | www.蜜桃av.com| 欧美日韩久 | 99精品国产一区二区青青牛奶 | 亚洲国产aⅴ成人精品无吗 国产精品永久在线观看 | 国产成人精品一区二区三 | 精品国产久| 少妇一级淫片免费播放 | 亚洲精品电影网在线观看 | 日韩欧美在线视频一区 | 亚洲精品国产一区 | 最新免费黄色网址 | 国产91av视频| 国产精品美女久久久久久不卡 | 中文亚洲视频 | 国产视频中文字幕 | 国产亚洲精品精品国产亚洲综合 | 精品国产乱码久久久久久丨区2区 | 亚洲精品自在在线观看 | 久久国产成人精品国产成人亚洲 | 每日更新av | 国产精品美女久久久av超清 | 另类一区| 黄视频网址| 香蕉视频1024 | 国产免费观看一区 | 三级av免费 | 欧美精品1区2区3区 精品国产欧美一区二区 | 97精品超碰一区二区三区 | 91人人看 | 免费一区二区三区 | 一二区成人影院电影网 | 999观看免费高清www | 毛片网站在线观看视频 | 日韩欧美三区 | 全免费a级毛片免费看视频免费下 | a毛片| 韩国精品在线观看 | 欧美www在线|