千層麵

千層麵

學習練習

簡介

基礎

變數

Elixir 是動態型別的語言,也就是說,變數的型別只會在執行時檢查。使用匹配運算子=,我們可以把任意型別的值綁定到一個變數名稱上:

# Bound an integer value of 1
count = 1
# You may re-bind variables
count = 2

# You may re-bind any type to a variable
count = false

# Strings can be created by enclosing characters within double quotes
message = "Success!"

模組

Elixir 是函式程式設計語言,所有具名函式都必須定義在_模組_中。defmodule關鍵字用來定義模組。在執行時,所有模組都可以被其他模組取用,不需要_存取修飾子_就能讓程式的其他部分看見它們。模組_概念上類似於其他程式語言中的_類別。

defmodule Calculator do
  # ...
end

具名函式

_具名函式_必須定義在模組中。def關鍵字用來定義_公開_的具名函式。

每個函式可以有零個或多個引數。函式中最後一個運算式的值總是會_被隱式回傳_。

defmodule Calculator do
  def add(x, y) do
    x + y
  end
end

呼叫函式時,要指定它的模組和函式名稱,並為函式的每個參數傳入引數。

sum = Calculator.add(1, 2)
# => 3

也可以用defp關鍵字取代def來定義_私有_函式。私有函式只能在定義它們的同一個模組內使用。

當在定義函式的同一個模組內呼叫它時,可以省略模組名稱。

你也可以用單行語法撰寫簡短的函式(注意關鍵字do前後的逗號,和冒號:)。

defmodule Calculator do
  def subtract(x, y) do
    private_subtract(x, y)
  end

  defp private_subtract(x, y), do: x - y
end

difference = Calculator.subtract(7, 2)
# => 5

difference = Calculator.private_subtract(7, 2)
# => ** (UndefinedFunctionError) function Calculator.private_subtract/2 is undefined or private
#       Calculator.private_subtract(7, 2)

函式的引數個數

我們常會用_引數個數_來指稱函式。函式的_引數個數_就是它接受的引數數量。

# add/3 because this function has three arguments, thus an arity of 3
def add(x, y, z) do
  x + y + z
end

命名慣例

模組名稱應該使用PascalCase。模組名稱必須以大寫字母A-Z開頭,可以包含字母a-zA-Z、數字0-9和底線_。

變數和函式名稱應該使用snake_case。變數或函式名稱必須以小寫字母a-z或底線_開頭,可以包含字母a-zA-Z、數字0-9和底線_,而且結尾可以是問號?或驚嘆號!。

標準函式庫

Elixir 擁有非常豐富且文件完整的標準函式庫。文件可以在 hexdocs.pm/elixir 線上查閱。把這個連結存起來,你會很常用到它喔!

大多數內建的資料型態都有對應的模組,提供處理該型別的函式。例如整數有Integer模組,字串有String模組,陣列有List模組等等。

值得一提的模組是Kernel模組。它是標準函式庫其餘部分的建構基礎,提供算術運算子、控制流程巨集等基本能力。Kernel模組的函式會自動匯入,所以你可以不加Kernel.前綴直接使用。

程式碼註解

註解可以用來留下筆記,給閱讀原始碼的其他開發者參考。Elixir 的單行註解以#開頭。

說明

在這道練習中,你會寫一些程式碼,幫助你依照最愛的食譜書做出一份美味的千層麵。

你有五個任務,全都和烹調千層麵所花費的時間有關。

1. 定義千層麵在烤箱中的預期時間(分鐘)

定義Lasagna.expected_minutes_in_oven/0函式,這個函式不接受任何引數,並回傳千層麵應該在烤箱中待幾分鐘。根據食譜書,預期的烤箱時間為 40 分鐘:

Lasagna.expected_minutes_in_oven()
# => 40

2. 計算剩餘的烤箱時間(分鐘)

定義Lasagna.remaining_minutes_in_oven/1函式,這個函式接受千層麵已經在烤箱中的實際分鐘數作為引數,並根據上一個任務算出的預期烤箱時間(分鐘),回傳千層麵還需要在烤箱中待幾分鐘。

Lasagna.remaining_minutes_in_oven(30)
# => 10

3. 計算備料時間(分鐘)

定義Lasagna.preparation_time_in_minutes/1函式,這個函式接受你加到千層麵中的層數作為引數,並回傳你準備千層麵花了幾分鐘,假設每一層需要花你 2 分鐘準備。

Lasagna.preparation_time_in_minutes(2)
# => 4

4. 計算總工作時間(分鐘)

定義Lasagna.total_time_in_minutes/2函式,這個函式接受兩個引數:第一個引數是你加到千層麵中的層數,第二個引數是千層麵已經在烤箱中的分鐘數。這個函式應該回傳你總共花了幾分鐘烹調千層麵,也就是備料時間(分鐘)加上千層麵當下已經在烤箱中待的分鐘數。

Lasagna.total_time_in_minutes(3, 20)
# => 26

5. 建立千層麵完成的提示通知

定義Lasagna.alarm/0函式,這個函式不接受任何引數,並回傳一則訊息,表示千層麵已經可以吃了。

Lasagna.alarm()
# => "Ding!"
透過 GitHub 編輯 連結會在新視窗或分頁中開啟
Elixir Exercism

準備好開始 千層麵 了嗎?

註冊 Exercism,透過 58 個概念168 個練習 和真人引導來學習並精通 Elixir,全部免費。