我正在研究一个关于elixir RNA转录的基本问题。然而,我的解决方案遇到了一些(对我来说)意想不到的行为:
defmodule RnaTranscription do
@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
_to_rna(dna)
end
def _to_rna([]), do: ''
def _to_rna([head | tail]), do: [_rna(head) | _to_rna(tail)]
def _rna(x) when x == 'A', do: 'U'
def _rna(x) when x == 'C', do: 'G'
def _rna(x) when x == 'T', do: 'A'
def _rna(x) when x == 'G', do: 'C'
end当解决方案运行时,我得到了错误,因为调用_rna函数时使用的整数与保护子句而不是字符不匹配。
The following arguments were given to RnaTranscription._rna/1:
# 1
65
lib/rna_transcription.ex:18: RnaTranscription._rna/1
lib/rna_transcription.ex:16: RnaTranscription._to_rna/1当灵丹妙药分裂成头部和尾部时,有没有办法强制它保留角色的值?
发布于 2019-09-20 12:14:11
除了列表'A'和字符?A之间的区别外,Michael完美地回答了这一问题,这段代码还有一个隐藏但重要的故障。
您使用的递归不是尾部优化的,这应该不惜一切代价避免。它通常可能会导致堆栈溢出。以下是TCO代码。
defmodule RnaTranscription do
def to_rna(dna), do: do_to_rna(dna)
defp do_to_rna(acc \\ [], []), do: Enum.reverse(acc)
defp do_to_rna(acc, [char | tail]),
do: do_to_rna([do_char(char) | acc], tail)
defp do_char(?A), do: ?U
defp do_char(?C), do: ?G
defp do_char(?T), do: ?A
defp do_char(?G), do: ?C
end
RnaTranscription.to_rna('ACTG')
#⇒ 'UGAC'或者,更好的是,通过理解
converter = fn
?A -> ?U
?C -> ?G
?T -> ?A
?G -> ?C
end
for c <- 'ACTG', do: converter.(c)
#⇒ 'UGAC'你甚至可以就地过滤它。
for c when c in 'ACTG' <- 'ACXXTGXX',
do: converter.(c)
#⇒ 'UGAC'发布于 2019-09-20 08:50:24
您可以使用?代码点运算符:
def _rna(x) when x == ?A, do: 'U'
def _rna(x) when x == ?C, do: 'G'
def _rna(x) when x == ?T, do: 'A'
def _rna(x) when x == ?G, do: 'C'严格地说,Elixir已经保持了角色的价值!字符是一个码位,它是一个整数。当您在'A'上匹配时,您是在一个字符列表上匹配,该列表是一个整数列表。也就是说,您正在尝试将65与[65]进行匹配。
https://stackoverflow.com/questions/58019729
复制相似问题