符咒 (Sigils)
使用和創設符咒 (sigils)。
符咒概述
Elixir 提供了用於表示和使用文字的替代語法。
一個符咒 (sigil) 將以波浪符號 ~ 開頭。
Elixir 核心已經提供一些內建的符咒,不過當我們需要時,也可以自行創造所需的符咒。。
可用符咒清單如下:
-
~C生成一個 不運算 轉義 (escaping) 或內插 (interpolation) 的符號列表 (character list) -
~c生成一個 運算 轉義或內插的符號列表 -
~R生成一個 不運算 轉義或內插的正規表達式 (regular expression) -
~r生成一個 運算 轉義或內插的正規表達式 -
~S生成一個 不運算 轉義或內插的字串 (string) -
~s生成一個 運算 轉義或內插的字串 -
~W生成一個 不運算 轉義或內插的字串列表 (word list) -
~w生成一個 運算 轉義或內插的字串列表 -
~N生成一個NaiveDateTime結構體
分隔符號清單如下:
-
<...>尖括號 (pointy brackets) -
{...}大括號 (curly brackets) -
[...]中括號 (square brackets) -
(...)小括號 (parentheses) -
|...|管線符號 (pipes) -
/.../斜線 (forward slashes) -
"..."雙引號 (double quotes) -
'...'單引號 (single quotes)
符號列表 (Char List)
符咒 ~c 和 ~C 分別生成不同的符號列表 (character lists)。
例如:
iex> ~c/2 + 7 = #{2 + 7}/
'2 + 7 = 9'
iex> ~C/2 + 7 = #{2 + 7}/
'2 + 7 = \#{2 + 7}'
可以看到小寫字母的 ~c 內插了計算結果,而大寫字母的 ~C 則沒有。
我們將發現,字母大寫/小寫系列是整個內建符咒的常見樣式。
正規表達式 (Regular Expressions)
符咒 ~r 和 ~R 用來表示正規表達式。
我們能在動態情況創設或在 Regex 函數中使用。
例如:
iex> re = ~r/elixir/
~r/elixir/
iex> "Elixir" =~ re
false
iex> "elixir" =~ re
true
我們可以看到,在第一個等式查驗中,Elixir 與正規表達式沒有相配。
這是因為它使用大寫字母。
由於 Elixir 支援相容 Perl 正規表達式(Perl Compatible Regular Expressions, PCRE),所以我們可以在符咒末尾加上 i 來關閉大小寫字母敏感。
iex> re = ~r/elixir/i
~r/elixir/i
iex> "Elixir" =~ re
true
iex> "elixir" =~ re
true
此外,Elixir 提供構建在 Erlang 正規表達式函式庫之上的 Regex API。
現在使用正規表達式符咒 (regex sigil) 來實現 Regex.split/2 :
iex> string = "100_000_000"
"100_000_000"
iex> Regex.split(~r/_/, string)
["100", "000", "000"]
感謝我們的符咒 ~r/_/。正如我們所看到的,字串 "100_000_000" 藉由下底線 (underscore) 被分割。
函數 Regex.split 回傳了一個列表。
字串 (String)
符咒 ~s 和 ~S 被用來產生字串資料。
例如:
iex> ~s/the cat in the hat on the mat/
"the cat in the hat on the mat"
iex> ~S/the cat in the hat on the mat/
"the cat in the hat on the mat"
兩者有什麼不同? 答案是內插和轉義序列 (escape sequences) 的用法,其差別與我們所看到的符號列表符咒相似。 如果我們再舉一個例子:
iex> ~s/welcome to elixir #{String.downcase "SCHOOL"}/
"welcome to elixir school"
iex> ~S/welcome to elixir #{String.downcase "SCHOOL"}/
"welcome to elixir \#{String.downcase \"SCHOOL\"}"
字串列表 (Word List)
字串列表符咒 (word list sigil) 時不時的會派上用場。 它可以節省敲擊鍵盤的次數與時間,同時減少程式庫的複雜性。 來看看這個簡單的例子:
iex> ~w/i love elixir school/
["i", "love", "elixir", "school"]
iex> ~W/i love elixir school/
["i", "love", "elixir", "school"]
我們可以看到在分隔符號之間鍵入的內容被空格分隔成一個列表。 實際上,這兩個例子沒有什麼區別。 而再一次,它們的差異來自內插和轉義序列。 現在來看下面的例子:
iex> ~w/i love #{'e'}lixir school/
["i", "love", "elixir", "school"]
iex> ~W/i love #{'e'}lixir school/
["i", "love", "\#{'e'}lixir", "school"]
真日期時間 (NaiveDateTime)
一個 NaiveDateTime 可以快速創設一個結構體 (struct) 來表示 不帶 時區的 DateTime 。
在大多數情況下,我們應該避免直接創設一個 NaiveDateTime 結構體。
不過,在模式比對下非常有用。
例如:
iex> NaiveDateTime.from_iso8601("2015-01-23 23:50:07") == {:ok, ~N[2015-01-23 23:50:07]}
自訂符咒 (Creating Sigils)
Elixir 的目標之一是成為一種可擴展 (extendable) 的程式語言。
因此您應該不會對於可以輕鬆自訂你自己的客製化符咒感到驚訝。
在這個例子中,我們將自訂一個符咒將字串轉換為大寫字母。
儘管在 Elixir 核心函式庫中存在這個 (String.upcase/1) 函數來實現,不過我們依然將圍繞著這個函數來自訂我們的符咒。
iex> defmodule MySigils do
...> def sigil_u(string, []), do: String.upcase(string)
...> end
iex> import MySigils
nil
iex> ~u/elixir school/
ELIXIR SCHOOL
首先我們定義一個名為 MySigils 的模組,並在該模組中創設一個名為 sigil_u 的函數。
由於現存的符咒空間 (sigil space) 中並不存在 ~u 符咒,所以我們使用這個名字。
這個 _u 表示我們希望使用 u 作為波浪符號 (tilde) 之後的符號 (character)。
在這個函數的定義中,函數本身必須有兩個參數 (arguments),一個輸入和一個列表。
Caught a mistake or want to contribute to the lesson? Edit this lesson on GitHub!