Sigils
การใช้งานและสร้าง Sigils
Sigils Overview
ใน Elixir คุณสามารถแสดงผลและจัดการกับตัวอักษรต่างๆได้ในอีก syntax หนึ่งได้ โดยใช้ sigils
การใช้งาน Sigil นั้นจะเริ่มโดยการใช้สัญลักษณ์ตัวหนอน ~ และตามด้วยตัวอักษรหนึ่งตัว ซึ่ง Elixir core นั้นมี sigil เบื้องต้นบางส่วนพร้อมสำหรับการใข้งานอยู่แล้ว แต่คุณก็สามารถสร้าง sigil ของตัวเองได้เช่นกัน
Sigils เบื้องต้นที่มีให้ใช้งาน:
-
~Cจะสร้าง list ของ character โดยที่ ไม่มี การ escaping หรือ interpolation -
~cจะสร้าง list ของ character โดยที่ มี การ escaping หรือ interpolation -
~Rจะสร้าง regular Expression โดยที่ ไม่มี การ escaping หรือ interpolation -
~rจะสร้าง regular Expression โดยที่ มี การ escaping หรือ interpolation -
~Sจะสร้าง string โดยที่ ไม่มี การ escaping หรือ interpolation -
~sจะสร้าง string โดยที่ มี การ escaping หรือ interpolation -
~Wจะสร้าง list ของ word โดยที่ ไม่มี การ escaping หรือ interpolation -
~wจะสร้าง list ของ word โดยที่ มี การ escaping หรือ interpolation -
~Nจะสร้าง struct ประเภทNaiveDateTime -
~Uจะสร้าง struct ประเภทDateTime(ตั้งแต่ Elixir 1.9.0)
สำหรับ delimiters มีได้ดังนี้:
-
<...>A pair of pointy brackets -
{...}A pair of curly brackets -
[...]A pair of square brackets -
(...)A pair of parentheses -
|...|A pair of pipes -
/.../A pair of forward slashes -
"..."A pair of double quotes -
'...'A pair of single quotes
Char List
Sigil ~c และ ~C ใช้สำหรับสร้าง list ของ character
อย่างเช่นในตัวอย่างต่อไปนี้
iex> ~c/2 + 7 = #{2 + 7}/
'2 + 7 = 9'
iex> ~C/2 + 7 = #{2 + 7}/
'2 + 7 = \#{2 + 7}'
จะเห็นได้ว่าสำหรับ sigil ~c (ตัวพิมพ์เล็ก) นั้น มีการคำนวณและแทนค่าตัวแปร ในขณะที่ sigil ~C (ตัวพิมพ์ใหญ๋) ไม่ได้ทำเช่นนั้น และคืนค่า charlists ตรงๆ ออกมา.
ข้อสังเกตุ: การใช้ตัวพิมพ์ใหญ่และตัวพิมพ์เล็กใน sigil จะเป็นแนวการใช้งานของ sigil ที่มาพร้อมกับ Elixir
Regular Expressions
Sigil ~r และ ~R ใช้สำหรับการสร้าง Regular Expressions.
เราสามารถสร้างเพื่อใช้งานทันที หรือเพื่อใช้งานในฟังก์ชันต่างๆของ Regex.
อย่างเช่นในตัวอย่างต่อไปนี้
iex> re = ~r/elixir/
~r/elixir/
iex> "Elixir" =~ re
false
iex> "elixir" =~ re
true
จะเห็นได้ว่า ในการทดสอบความเท่ากันอันแรกนั้นพบว่า Elixir นั้นไม่ match กับ Regular Expression เนื่องจากเรื่องของตัวพิมพ์ใหญ่พิมพ์เล็ก
ที่เป็นเช่นนี้เพราะ Elixir นั้นรองรับ Regular Expression แบบ Perl Compatible Regular Expressions (PCRE) จึงจำเป็นต้องเพิ่ม i ต่อท้าย sigil ในตอนสร้าง เพื่อให้ regular expression นั้นไม่เป็น case sensitivity
iex> re = ~r/elixir/i
~r/elixir/i
iex> "Elixir" =~ re
true
iex> "elixir" =~ re
true
นอกจากนี้ Elixir ได้มี Regex API ให้เรียกใช้งาน ซึ่งสร้างขึ้นบน regular expression library ของ Erlang
เมื่อทำการใช้ Regex.split/2 คู่กับ Regex sigil
iex> string = "100_000_000"
"100_000_000"
iex> Regex.split(~r/_/, string)
["100", "000", "000"]
อย่างที่เห็นว่า string "100_000_000" ได้ถูกแบ่งโดย underscore เนื่องจาก sigil ~r/_/ ที่สร้างขึ้น และฟังก์ชัน Regex.split ได้ทำการ return เป็น list ออกมา
String
Sigil ~s และ ~S ใช้สำหรับการสร้างข้อมูล string
อย่างเช่นในตัวอย่างต่อไปนี้
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"
ถ้าดูจากตัวอย่างข้างต้นนี้ คุณอาจจะไม่เห็นความแตกต่าง แต่จริงๆแล้ว ความแตกต่างนั้นเหมือนกับ Sigil ของ Character List ซึ่งก็คือการ escaping และ interpolation ดังเช่นตัวอย่างถัดไป
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
Sigil word list มีประโยชน์ในบางสถานการณ์ มันสามารถลดเวลา ลดการพิมพ์ และลดความซับซ้อนของใน codebase ของคุณได้ อย่างเช่นตัวอย่างต่อไปนี้
iex> ~w/i love elixir school/
["i", "love", "elixir", "school"]
iex> ~W/i love elixir school/
["i", "love", "elixir", "school"]
จะเห็นได้ว่า สิ่งที่อยู่ใน delimiter นั้นถูกคั่นและตัดด้วย whitespace ออกมาเป็น list แต่ผลลัพธ์ของสองตัวอย่างข้างต้นนั้นไม่มีความแตกต่าง นั่นก็เป็นเพราะการใช้ sigil สำหรับการ escaping และ interpolation นั่นเอง ดังเช่นตัวอย่างถัดไป
iex> ~w/i love #{'e'}lixir school/
["i", "love", "elixir", "school"]
iex> ~W/i love #{'e'}lixir school/
["i", "love", "\#{'e'}lixir", "school"]
NaiveDateTime
Sigil NaiveDateTime สามารถใช้เพื่อสร้าง struct DateTime ที่ไม่มี timezone
ในส่วนใหญ่ เราควรจะหลีกเลี่ยงการสร้าง struct NaiveDateTime โดยตรง
แต่จะมีประโชน์มากสำหรับกรณีที่ใช้เพื่อการทำ Pattern Matching เช่น
iex> NaiveDateTime.from_iso8601("2015-01-23 23:50:07") == {:ok, ~N[2015-01-23 23:50:07]}
DateTime
Sigil DateTime สามารถใช้เพื่อสร้าง struct DateTime พร้อมกับ UTC timezone เนื่องจากเป็น UTC timezone นั้น เมื่อทำการเปรียบเทียบกับ DateTime string ที่อาจจะอยู่กันคนละ timezone จึงจำเป็นต้องมี offset (หน่วยวินาที) เพื่อใช้ในการเปรียบเทียบเพิ่มเติม
ตัวอย่างดังนี้
iex> DateTime.from_iso8601("2015-01-23 23:50:07Z") == {:ok, ~U[2015-01-23 23:50:07Z], 0}
iex> DateTime.from_iso8601("2015-01-23 23:50:07-0600") == {:ok, ~U[2015-01-24 05:50:07Z], -21600}
Creating Sigils
หนึ่งในเป้าหมายหลักของ Elixir คือการทำภาษานี้ให้เป็น extendable programming language (ภาษาที่สามารถต่อขยายได้) มันจึงง่ายที่จะสามารถพัฒนา sigil ขึ้นมาเพื่อตอบโจทย์การใช้งานใหม่ๆ ได้
ในตัวอย่างนี้ จะทำการสร้าง sigil เพื่อทำการแปลง string ให้เป็นตัวพิมพ์ใหญ่ทั้งหมด
และเนื่องจากใน Elixir core นั้นมีฟังก์ชั่น String.upcase/1 อยู่แล้ว เราจะทำการครอบฟังก์ชันดังกล่าวด้วย sigil ที่สร้างขึ้น
iex> defmodule MySigils do
...> def sigil_p(string, []), do: String.upcase(string)
...> end
iex> import MySigils
nil
iex> ~p/elixir school/
ELIXIR SCHOOL
ในขั้นตอนแรกแรก เราทำการสร้าง module ที่มีชื่อว่า MySigils และทำการสร้างฟังก์ชัน sigil_p ขึ้นมา โดย คำต่อท้าย _p ใน ฟังก์ชัน sigil_p แสดงว่าเราจะทำการกำหนดให้ p เป็น character ที่ต่อจากตัวหนอน ~ เนื่องจากไม่มี sigil ~p อยู่ในปัจจุบัน โดยที่ฟังก์ชันที่สร้างขึ้นนั้นต้องรับ 2 arguments คือ input และ list
Caught a mistake or want to contribute to the lesson? Edit this lesson on GitHub!