Elixir中的"@"有什么作用?

4

我一直在查看一些编码解决方案,它们展示了“@”符号;但是,通过查阅文档,我似乎无法弄清楚该符号的作用。

在Elixir中,“@”符号有什么作用,为什么重要呢?

下面是一个例子:

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

在过去的两年里,有什么变化让你更喜欢另一个答案了?:P - Adam Millerchip
2个回答

5
在Elixir中,@符号表示模块属性,这些属性在编译时非常有用。你通常会在OO语言中放置类常量的地方看到它们。
然而,模块属性比你在OO语言中发现的更加微妙。以下是一些重要的要点:
  1. 如果你习惯于在面向对象的编程中定义类常量,那么请注意,Elixir不使用=来赋值(即使你可能已经养成了这样的习惯)。其语法更像是function input,可选的括号可以省略。

  2. 模块属性可以在模块中多次重新定义。你会经常看到使用@doc属性来注释后面的函数,使用@spec属性来注释函数的输入/输出,或者在测试中使用@tag属性来改变后续测试的输入。这可以提供一种有用的方式来将大量的值放在函数逻辑之外,以提高可读性。

  3. 模块属性可以进行累加。通常情况下,每个属性实例都会重新分配其值,但是如果在注册属性时设置accumulate: true,则随后的定义将进行累加,以便读取属性将返回所有累加值。从文档页面获取:

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

模块属性在编译时评估。由于它们可能会提高重要的模块级值的可见性,您可能会想做一些类似于存储ENV值的事情:
defmodule Trouble do
  @my_value System.fetch_env("BOOM") # <-- don't do this!
end

最近版本的Elixir会在尝试这样做时显示警告(某些值,如捕获的函数,将引发错误),因此,一般来说,最好保持模块属性简单和静态。


5
这是一个模块属性的语法:
模块属性在Elixir中有三个作用:
  1. 它们用于为模块添加注释,通常包含用户或VM将要使用的信息。
  2. 它们作为常量。
  3. 它们作为编译期间要使用的临时模块存储。
属性在编译时由编译器读取,因此它们不能在运行时访问或更改。在运行时,它们将被编译器计算出的值所替换。
在您的情况下,这是一个函数:
defp get_rna_for_dna(dna_nucleotide) do
  @dna_nucleotide_to_rna_nucleotide_map[dna_nucleotide]
end

最终被编译为:

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

@spec用于定义类型规范@doc用于文档化。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接