简体   繁体   English

“@”在 Elixir 中有什么作用?

[英]What does “@” do in Elixir?

I have been looking through some coding solutions and they show the "@" symbol;我一直在查看一些编码解决方案,它们显示了“@”符号; however, I can't really seem to figure out what that symbol does by looking through documentation.但是,我似乎无法通过查看文档来真正弄清楚该符号的作用。

What does the @ symbol do in Elixir, and why is it important? @ 符号在 Elixir 中有什么作用,为什么它很重要?

Here is an example:下面是一个例子:

defmodule RNATranscription do
  @dna_nucleotide_to_rna_nucleotide_map %{
    # `G` -> `C`
    71 => 67,

    # `C` -> `G`
    67 => 71,

    # `T` -> `A`
    84 => 65,

    # `A` -> `U`
    65 => 85
  }

  @doc """
  Transcribes a character list representing DNA nucleotides to RNA

  ## Examples

  iex> RNATranscription.to_rna('ACTG')
  'UGAC'
  """
  @spec to_rna([char]) :: [char]
  def to_rna(dna) do
    dna
    |> Enum.map(&get_rna_for_dna/1)
  end

  defp get_rna_for_dna(dna_nucleotide) do
    @dna_nucleotide_to_rna_nucleotide_map[dna_nucleotide]
  end
end

The @ symbol in Elixir denotes module attributes , which are useful compile-time settings. Elixir 中的@符号表示 模块属性,这是有用的编译时设置。 You often see them in places where you might put class constants in an OO language.您经常在可能将类常量放入 OO 语言的地方看到它们。

However, module attributes are more subtle than what you might find in an OO language.然而,模块属性比您在面向对象语言中可能发现的更微妙。 Here are some important takeaways:以下是一些重要的要点:

  1. They do not use the = to assign a value (as you might be in the habit of doing if you are used to defining class constants in OO-land).它们使用=来分配值(如果您习惯于在 OO-land 中定义类常量,您可能会习惯这样做)。 The syntax is more like function input where the optional parentheses are dropped.语法更像是function input ,其中删除了可选的括号。

  2. Module attributes can be redefined multiple times throughout the module.模块属性可以在整个模块中多次重新定义。 You'll see this frequently with @doc attributes that annotate the function that follows it, with @spec which annotates the function input/output, or inside tests with @tag to change the inputs to the test that follows it.你会经常看到@doc属性注释它@spec的函数, @spec注释函数输入/输出,或者在测试内部用@tag更改输入到它@tag的测试。 This can offer a useful way to put big values out of the way of the function logic to improve readability.这可以提供一种有用的方法来将大值排除在函数逻辑之外以提高可读性。

  3. Module attributes can be accumulated .模块属性可以累积 Normally, each instance of an attribute reassigns its value, but if you set accumulate: true when you register the attribute, then subsequent definitions will accumulate so that reading the attribute will return all the accumulated values.通常,属性的每个实例都会重新分配其值,但是如果您在注册属性时设置了accumulate: true ,那么后续定义将进行累加,以便读取该属性将返回所有累加值。 From the doc page:从文档页面:

defmodule MyModule do
  Module.register_attribute(__MODULE__, :custom_threshold_for_lib, accumulate: true)

  @custom_threshold_for_lib 10
  @custom_threshold_for_lib 20
  @custom_threshold_for_lib #=> [20, 10]
end
  1. Module attributes are evaluated at compile-time .模块属性在编译时评估。 Because they can raise visibility on important module-wide values, you might be tempted to do something like stash an ENV value:因为它们可以提高对重要的模块范围值的可见性,您可能会想做一些类似隐藏 ENV 值的事情:
defmodule Trouble do
  @my_value System.fetch_env("BOOM") # <-- don't do this!
end

More recent versions of Elixir will show warnings if you attempt to do this (and some values, eg captured functions, will raise an error), so as a general rule of thumb, it's best to keep the module attributes simple and static.如果您尝试这样做,更新版本的 Elixir 将显示警告(并且某些值,例如捕获的函数,将引发错误),因此作为一般经验法则,最好保持模块属性简单和静态。

It's the syntax for a module attribute :这是 模块属性的语法:

Module attributes in Elixir serve three purposes: Elixir 中的模块属性有三个用途:

  1. They serve to annotate the module, often with information to be used by the user or the VM.它们用于注释模块,通常包含用户或 VM 使用的信息。
  2. They work as constants.它们作为常量工作。
  3. They work as a temporary module storage to be used during compilation.它们用作编译期间使用的临时模块存储。

Attributes are read by the compiler at compile-time, so they cannot be accessed or changed at runtime.属性由编译器在编译时读取,因此无法在运行时访问或更改。 At runtime, they will have been replaced with whatever was evaluated by the compiler.在运行时,它们将被编译器评估的任何内容替换。

In your case, this function:在您的情况下,此功能:

defp get_rna_for_dna(dna_nucleotide) do
  @dna_nucleotide_to_rna_nucleotide_map[dna_nucleotide]
end

Is effectively compiled to this:有效地编译为:

defp get_rna_for_dna(dna_nucleotide) do
  %{
    71 => 67,
    67 => 71,
    84 => 65,
    65 => 85
  }[dna_nucleotide]
end

@spec is used to define typespecs , @doc is for documentation. @spec用于定义类型规范@doc用于文档。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM