當前位置: 首頁>>編程示例 >>用法及示例精選 >>正文


Elixir Kernel.@expr用法及代碼示例

Elixir語言中 Kernel.@expr 相關用法介紹如下。

用法:

@expr
(宏)

模塊屬性一元運算符。

讀取和寫入當前模塊中的屬性。

屬性的典型示例是注釋模塊實現了 OTP 行為,例如 GenServer

defmodule MyServer do
  @behaviour GenServer
  # ... callbacks ...
end

默認情況下,Elixir 支持 Erlang 支持的所有模塊屬性,但也可以使用自定義屬性:

defmodule MyServer do
  @my_data 13
  IO.inspect(@my_data)
  #=> 13
end

與 Erlang 不同,這些屬性默認不存儲在模塊中,因為 Elixir 中通常使用自定義屬性來存儲在編譯時可用的臨時數據。可以使用 Module.register_attribute/3 將自定義屬性配置為更接近 Erlang。

重要提示:庫和框架應考慮使用下劃線作為私有模塊屬性的前綴,例如@_my_data,以便代碼完成工具不會在建議和提示中顯示它們。

最後,注意屬性也可以在函數內部讀取:

defmodule MyServer do
  @my_data 11
  def first_data, do: @my_data
  @my_data 13
  def second_data, do: @my_data
end

MyServer.first_data()
#=> 11

MyServer.second_data()
#=> 13

需要注意的是,讀取屬性會獲取其當前值的快照。換句話說,該值是在編譯時讀取的,而不是在運行時讀取的。檢查 Module 模塊是否有其他函數來操作模塊屬性。

注意力!同一屬性的多個引用

如上所述,每次讀取模塊屬性時,都會對其當前值進行快照。因此,如果您在模塊屬性中存儲較大的值(例如,在模塊屬性中嵌入外部文件),則應避免多次引用同一屬性。例如,不要這樣做:

@files %{
  example1: File.read!("lib/example1.data"),
  example2: File.read!("lib/example2.data")
}

def example1, do: @files[:example1]
def example2, do: @files[:example2]

在上文中,對@files 的每個引用都可能在end-up 中帶有整個@files 模塊屬性的完整且單獨的副本。相反,在私有函數中引用一次模塊屬性:

@files %{
  example1: File.read!("lib/example1.data"),
  example2: File.read!("lib/example2.data")
}

defp files(), do: @files
def example1, do: files()[:example1]
def example2, do: files()[:example2]

注意力!編譯時依賴

請記住對其他模塊的引用,即使在模塊屬性中,也會生成對所述模塊的編譯時依賴項。

例如,采用這種常見模式:

@values [:foo, :bar, :baz]

def handle_arg(arg) when arg in @values do
  ...
end

雖然上麵沒問題,但想象一下,如果您在模塊屬性中有實際的模塊名稱,如下所示:

@values [Foo, Bar, Baz]

def handle_arg(arg) when arg in @values do
  ...
end

上麵的代碼將定義對模塊 FooBarBaz 的編譯時依賴,如果它們中的任何一個發生變化,當前模塊將不得不重新編譯。在這種情況下,最好完全避免使用模塊屬性:

def handle_arg(arg) when arg in [Foo, Bar, Baz] do
  ...
end

相關用法


注:本文由純淨天空篩選整理自elixir-lang.org大神的英文原創作品 Kernel.@expr。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。