Macro ใน Elixir เป็นกระบวนการ code transformation คือรับ AST (Abstract Syntax Tree เป็นโครงสร้างแทน source code) เป็น input แล้วสามารถ process บางอย่างเพื่อส่ง AST output ที่อยากได้กลับออกไป
Elixir มี use/2 ซึ่งเป็น macro ที่ติดมากับ Kernel module สำหรับให้เราสร้าง code template แล้วใช้ use เพื่อ inject โค้ดเข้ามาใน module ที่อื่นที่เราต้องการได้
use รับค่า 2 อย่างคือ ชื่อ Module ที่จะเป็นส่วน generate code ที่จะถูก inject เข้ามา กับ option อื่นๆถ้ามี
ส่วน Module ที่ถูก inject เข้ามาสามารถสร้าง code template ได้โดยการสร้าง macro ชื่อ __using__/1
โดยรับ options เป็น parameter แล้วให้เขียนโค้ดที่ต้องการ inject ไว้ใน macro __using__
นี่แหละ
ตัวอย่างเช่น เราจะสร้าง module Greeter เพื่อเก็บ template ของ function say/0
แบบนี้
defmodule Greeter do
defmacro __using__(opts) do
quote do
def say do
opts = unquote(opts)
name = opts[:name] || "World"
IO.puts("Hello #{name}")
end
end
end
end
เราสามารถ inject function say/0
เข้าไปใน module อื่นได้โดยใช้ use
แบบนี้
defmodule Hello do
use Greeter,
name: "Por"
end
ทำให้ module Hello มี method say
ที่จะ print Hello Por
แบบนี้
iex(4)> Hello.say
Hello Por
:ok
นี้คือกลไกการทำงานของ use/2
ที่แม้ว่าเราอาจจะไม่ได้เขียน module template เอง แต่คงทำให้เข้าใจมากขึ้นเพราะเราจะได้ใช้ use/2
บ่อยมากๆกับ library อย่าง Phoenix หรือ Ecto
Top comments (0)