Khi mới tiếp cận với Elixir các bạn có thể sẽ phân vân điểm khác nhau giữa các từ khoá trên. Bài viết này so sánh các từ khoá đó thông qua cách sử dụng
1. import
Hiểu đơn giản nó sẽ bê toàn bộ functions và macros của module B vô module A để sử dụng. Mình có thể gọi tắt 1 function trong B mà không cần bắt đầu bằng tên module.
defmodule A do
  def say_world() do
    IO.puts("world")
  end
  defmacro if_unless(expr, opts) do
    quote do
      if !unquote(expr), unquote(opts)
    end
  end
end
defmodule B do
  import A
  def say_hello do
    IO.puts("Hello ")
    if_unless false do
      say_world()
    end
  end
end
Có thể sử dụng thêm 2 từ khóa only nếu chỉ muốn lấy 1 số hàm, marco hoặc từ khóa except nếu muốn loại từ hàm hay macro nào đó
import List, only: [flatten: 1]
import String, except: [split: 2]
Import có thể sử dụng bên trong function và có scope chỉ ở trong function đó.
defmodule Math do
    def some_function do
        # 1) Disable "if/2" from Kernel
        import Kernel, except: [if: 2]
        # 2) Require the new "if/2" macro from MyMacros
        import MyMacros
        # 3) Use the new macro
        if do_something, it_works
    end
end
Lưu ý: Các hàm bắt đầu bằng _ sẽ không được import. Ví dụ: (__build__, ...)
2. require
Khi muốn sử dụng marco của 1 module nào đó, bắt buộc phải require module đó trước khi gọi marco
defmodule A do
  def say_world() do
    IO.puts("world")
  end
  defmacro if_unless(expr, opts) do
    quote do
      if !unquote(expr), unquote(opts)
    end
  end
end
defmodule B do
  require A
  def say_hello do
    IO.puts("Hello ")
    A.if_unless false do
      A.say_world()
    end
  end
end
3. alias
Dùng để setup 1 alias name cho 1 module. Mặc định thì alias sẽ lấy phần cuối cùng trong tên module làm tên alias.
defmodule A do
    alias Foo.Bar.Baz
    def funcA do
        Baz.some_func()
    end
end
Có thể sử dụng key as để định nghĩa 1 tên khác.
defmodule A do
    alias Foo.Bar.Baz, as: FBar
    def funcA do
        FBar.some_func()
    end
end
Mình có thể định nghĩa nhiều alias có module tương tự nhau trong cùng 1 hàng
alias Foo.Bar
alias Foo.Baz
alias Foo.Biz
> alias Foo.{Bar, Baz, Biz}
Chú ý: import/2, require/2 và alias/2 có thế định nghĩa trong từng function khác nhau không nhất thiết phải để ngay sau  defmodule và nó không ảnh hưởng scope lẫn nhau.
4. use
Thường xài kiểu như abstract, Khi module B use module A, nó sẽ invoke marco __using__ trong module A
defmodule A do
  defmacro __using__(opts) do
    quote do
      IO.puts("Hello ")
    end
  end
end
defmodule B do
  use A, key1: "abc"
  def say_hello do
    IO.puts("World")
  end
end
đoạn code trên tương đương với
defmodule B do
  B.__using__([key1: "abc"])
  def say_hello do
    IO.puts("World")
  end
end
use thường được dùng khi muốn định nghĩa 1 behavior cho 1 module. Ví dụ trong Phoenix Framework. Controller được định nghĩa
defmodule ApiWeb do
...
    def controller do
        quote do
            use Phoenix.Controller, namespace: ApiWeb
            import Plug.Conn
            import ApiWeb.Router.Helpers
            import ApiWeb.Gettext
            require Logger
        end
    end
...
end
defmodule ApiWeb.PageController do
    use ApiWeb, :controller
    ...
end
Lưu ý: Không nên định nghĩa hàm ở trong __using__/1
Kết
Các bạn có thể tham gia vào channel #elixir ở  cộng đồng Ruby Việt Nam để thảo luận thêm về các vấn đề khi lập trình với elixir :)
    
Top comments (0)