02. Elixir 學習 - 跨出第一步

/elixir/start/cover.webp
Cover Photo by Aamir Suhail on Unsplash

開頭

每個人學習方式都不盡相同。

或許很多人會建議你應該提前做準備,先做好各種理論的學習。希望能讓你避開問題,從而減少失敗。但,那些建議真的能夠讓你避開所有問題嗎? 還是只是讓你緩慢地失敗,到後來失敗之後反而不知所措,一蹶不振。

對我來說,我喜歡的學習方式是 Learning by Doing 與 Fail Fast。直接開始做就對了,錯了也沒關係。我希望更早遇到錯誤與失敗,在每次失敗之後與修正失敗之後,我站起來的腳步也會越來越來穩固。

當然,這不一定適合所有人。但,歡迎參考。

start/fig01.avif

Figure 01. by Aaron Davis

為甚麼要學習 Elixir?

因為好玩。學習就是快樂的泉源。難道你已經忘了小時候那最純粹的快樂了嗎?

start/fig02.avif

Figure 02. by Ben White on Unsplash

簡略介紹 Elixir

Elixir 是一個基於 Erlang 虛擬機器的函數式、面向並列的通用程式語言。Elixir 以 Erlang 為基礎,支援分散式、高容錯、即時應用程式的開發,亦可通過巨集實現元程式設計對其進行擴充,並通過協定支援多型。

– Wikipedia

Elixir 是一個需要編譯的程式語言 (Compiled),但用起來可以像直譯式語言一樣 (Interpreted),可以在 Shell 直接執行指令馬上就可以得到回應,像 Python 一樣。

Elixir 是函數式類型的語言,程式的組成都是使用函數 (Functions),並不需要學習甚麼 OO 物件導向概念。 再來就是 Elixir 中的變數 (Variables) 都是不可變動的 (Immutable)。在撰寫並行運算的時候相對於其他語言簡單許多,不需要擔心變數何時會被其他線程串改。

Elixir 擴充性很高,最好的證明就是 Elixir 本身有 90% 以上都是用自己寫出來。

去看看 ”Elixir 原始碼庫“。

start/fig03.avif

Elixir 可以用來幹嘛?

Elixir 可以用來做後端伺服器 (Back End) 或是全端的網頁 (Full Stack Web) 甚至嵌入式系統 (Embedded) 與 IoT 相關的都有。若是不知道前面說的那些是甚麼東西,無所謂,反正學下去就知道可以幹甚麼了。

這邊就給一個著名的例子,聊天軟體 Discord 的後端伺服器是用 Elixir 打造的: Real time communication at scale with Elixir at Discord 。

若想知道更多有哪些公司有在用 Elixir,請參考 Elixir 案例。

Elixir 的學習資源

網上有很多資源可以學習 Elixir,要花錢的學習資源我這邊就都略過了。

我這邊整理出一些免費的學習資源給各位參考。

  • elixir-lang.org

    官方指南。只有英文。內有說明加上範例。

  • Elixir School

    學習手冊。有中文。可以拿來跟官方指南一起用,相輔相成。

  • Exercism

    提供練習題目,直接動手寫碼來學習語言的平台。雖然沒有中文,但這平台可以讓你的學習速度倍增。

除此之外,還可以透過 Github 上搜索別人的專案來參考學習,例如:

IDE

我主要使用的是 Visual Studio Code,若你熟悉其他 IDE ,請隨意。

VSCode 插件

  • ElixirLS

    稍微改一下 ElixirLS 的設定

    Ctrl + Shift + P

    打開 Preferences: Open User Setting

    可以直接修改 json 或是使用 UI 的方式來更改以下設定。

json
"elixirLS.suggestSpecs": false,
"elixirLS.dialyzerEnabled": true,
"elixirLS.signatureAfterComplete": false,
"elixirLS.fetchDeps": false,

環境確認

查看已安裝 Elixir 版本

shell
elixir -v

結果

shell
❯ elixir -v
Erlang/OTP 25 [erts-13.0] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [jit:ns]
Elixir 1.13.4 (compiled with Erlang/OTP 25)

Hello World

依造慣例,我們第一件事情就是寫個程式來輸出 Hello World 到螢幕上。

使用 iex

iex 是 Elixir 的 REPL interactive shell (互動式的 shell)

打開 shell,啟動 iex

shell
iex

結果

shell
❯ iex
Erlang/OTP 25 [erts-13.0] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [jit:ns]
Interactive Elixir (1.13.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)>

查看幫助,輸入

shell
iex(1)> h

輸出 Hello World 的程式碼

shell
iex(2)> IO.puts "Hello World"
Hello World
:ok
iex(3)>

IO.puts "Hello World" 這裡面的 IO 是一個內建 module。裡面有一個 function puts ,可以讓我們把輸入的字串印列到電腦螢幕上。

若想了解更多有關 IO 這個 module,

第一種方式,可以使用 iex 的 h

shell
iex(3)> h IO

第二種方式,到 Elixir 的 hexdocs 上查看

接下來我們來嘗試用其他方法來寫 Hello World 吧。

結束 iex,目前我們直接 Ctrl + C 兩次就好了。

使用 elixir 執行 helloWorld.ex

接下來我們會創建一個 .ex 的文檔來寫 Hello World。

.ex 與 .exs 的差別。

.ex 與 .exs 都是 Elixir 所使用的副檔名。差別只是 .ex 會經過編譯,而 .exs 會像 script 檔案一樣不經過編譯直接執行。我們暫時不需要去深究。

建立 helloWorld.ex ,輸入以下後存檔

helloWorld.ex
elixir
IO.puts "Hello World"

在文檔的路徑打開 shell 輸入

shell
elixir helloWorld.ex

結果

shell
❯ elixir helloWorld.ex
Hello World

使用 iex 執行 helloWorld.ex

使用 iex 來跑剛剛建立的 helloWorld.ex

shell
iex helloWorld.ex

結果

shell
❯ iex helloWorld.ex
Erlang/OTP 25 [erts-13.0] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [jit:ns]
Hello World
Interactive Elixir (1.13.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)>

先別結束 iex ,我們打開 helloWorld.ex 修改一下後存檔

helloWorld.ex
elixir
IO.puts "Hello World 2"

回到 iex

shell
iex> c "helloWorld.ex"

結果

shell
iex(1)> c "helloWorld.ex"
Hello World 2
[]
iex(2)>

c 這個 function 可以讓我們重新編譯指定的檔案。

若要查看更多說明:

shell
iex> h c
Optional parentheses

有些同學可能會疑問,呼叫 function 的時候不用括號 () 嗎? 為甚麼不是 c("helloWorld.ex")? 答案是可加可不加,這邊最主要是為了讓各位同學少打幾個字元。更多細節,請參考: #Optional parentheses。

使用 mix 創建 project

接下來,我們來嘗試創建一個 Hello World 的專案

shell
mix new helloworld

這樣會創建一個 helloworld 的資料夾,接下來我們到 helloworld/lib,可以在 lib 的資料夾中看到檔案 helloworld.ex。

helloworld.ex
elixir
defmodule Helloworld do
@moduledoc """
Documentation for `Helloworld`.
"""
@doc """
Hello world.
## Examples
iex> Helloworld.hello()
:world
"""
def hello do
:world
end
end

預設已經幫我寫好了一個 module 與 function,在 @doc 裡面也有範例告訴我們如何使用,我們來試試看。

在 helloworld 資料夾裡打開 shell ,輸入以下指令可以讓我們用 iex 來打開這個專案

shell
iex -S mix

結果

shell
❯ iex -S mix
Erlang/OTP 25 [erts-13.0] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [jit:ns]
Compiling 1 file (.ex)
Interactive Elixir (1.13.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)>

我們來測試看看

shell
iex> Helloworld.hello()

結果

shell
iex(1)> Helloworld.hello()
:world
iex(2)>

如同 @doc 裡寫的一樣,這個 hello() function 會輸出 :world

先不關閉 iex,我們來修改 helloworld.ex,在最後新增一行 IO.puts "Hello World"

helloworld.ex
elixir
defmodule Helloworld do
@moduledoc """
Documentation for `Helloworld`.
"""
@doc """
Hello world.
## Examples
iex> Helloworld.hello()
:world
"""
def hello do
:world
end
end
IO.put "Hello World"

然後回到我們的 iex ,輸入以下指令重新編譯

shell
iex> recompile

結果

shell
iex(2)> recompile
Compiling 1 file (.ex)
Hello World
:ok
iex(3)>

我們又輸出了 Hello World 了。

總結

本篇文章最主要就是用 Elixir 來寫一個能在電腦螢幕上顯示 Hello World 字串的電腦程式。

我們嘗試了 IO 這個 module 裡的 puts function 來做出我們的程式。

也用了以下很多不同的方式來跑這個程式

  • iex
  • elixir
  • mix

最後

我想說,還是自己動手學最棒了!

start/fig04.avif

Figure 04. by Zac Durant on Unsplash

誰說一定要參加甚麼管它付費還是免費的課程才能學寫程式? 才能當軟體工程師呢? 我們的熱情不是靠來自他人意義不名的審核來下定論的。

只有我們自己,才是對我們自己來說 最好 最棒 的導師。

讓我們繼續一起學習下去吧。

完結