我一直在研究一些编码解决方案,它们显示“@”符号;但是,我似乎无法通过查看文档来真正弄清楚该符号的作用。
@ 符号在 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
Run Code Online (Sandbox Code Playgroud)
这是模块属性的语法:
Elixir 中的模块属性有三个用途:
- 它们用于注释模块,通常包含用户或虚拟机使用的信息。
- 它们作为常量工作。
- 它们作为编译期间使用的临时模块存储。
属性由编译器在编译时读取,因此无法在运行时访问或更改。在运行时,它们将被编译器评估的内容替换。
在你的情况下,这个函数:
defp get_rna_for_dna(dna_nucleotide) do
@dna_nucleotide_to_rna_nucleotide_map[dna_nucleotide]
end
Run Code Online (Sandbox Code Playgroud)
有效地编译为:
defp get_rna_for_dna(dna_nucleotide) do
%{
71 => 67,
67 => 71,
84 => 65,
65 => 85
}[dna_nucleotide]
end
Run Code Online (Sandbox Code Playgroud)
@spec
用于定义typespecs,@doc
用于文档。
Elixir 中的符号@
表示模块属性,这是有用的编译时设置。您经常会在 OO 语言中放置类常量的地方看到它们。
然而,模块属性比 OO 语言中的属性更加微妙。以下是一些重要的要点:
它们不使用来=
赋值(如果您习惯在 OO 领域定义类常量,您可能会习惯这样做)。语法更像是function input
删除可选括号的地方。
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. This can offer a useful way to put big values out of the way of the function logic to improve readability.
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. 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
Run Code Online (Sandbox Code Playgroud)
defmodule Trouble do
@my_value System.fetch_env("BOOM") # <-- don't do this!
end
Run Code Online (Sandbox Code Playgroud)
More recent versions of Elixir will show warnings if you attempt to do this (and some values, e.g. captured functions, will raise an error), so as a general rule of thumb, it's best to keep the module attributes simple and static.