【问题标题】:What does "@" do in Elixir?“@”在 Elixir 中有什么作用?
【发布时间】:2021-07-07 20:43:21
【问题描述】:

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

@符号在 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

【问题讨论】:

    标签: syntax elixir


    【解决方案1】:

    Elixir 中的@ 符号表示module attributes,这是有用的编译时设置。您经常会在可能将类常量放入 OO 语言的地方看到它们。

    但是,模块属性比您在 OO 语言中可能发现的更微妙。以下是一些重要的要点:

    1. 他们确实使用= 来分配值(如果您习惯于在OO 领域定义类常量,您可能会习惯这样做)。语法更像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
    
    1. 模块属性在编译时进行评估。因为它们可以提高对重要模块范围值的可见性,所以您可能会想执行一些操作,例如存储 ENV 值:
    defmodule Trouble do
      @my_value System.fetch_env("BOOM") # <-- don't do this!
    end
    

    如果您尝试这样做,最新版本的 Elixir 将显示警告(并且某些值,例如捕获的函数,会引发错误),因此作为一般经验法则,最好保持模块属性简单和静态.

    【讨论】:

      【解决方案2】:

      这是module attribute 的语法:

      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 用于定义typespecs@doc 用于文档。

      【讨论】:

        猜你喜欢
        • 2015-05-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-26
        • 2015-11-22
        • 2017-05-22
        • 1970-01-01
        相关资源
        最近更新 更多