【问题标题】:Elixir characters being treated as integers, not characters when splitting to head and tailElixir 字符被视为整数,而不是拆分为头部和尾部时的字符
【发布时间】:2019-09-20 12:55:12
【问题描述】:

我正在研究长生不老药的一个基本问题 - 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

有没有办法强制长生不老药在分裂成头尾时将值保留为字符?

【问题讨论】:

  • 旁注:以下划线开头的公共函数命名是反惯用的。将defp 用于私有函数并将它们称为do_rna 而不是_rna,这是常规的。

标签: elixir


【解决方案1】:

除了列表 'A' 和 Michael 完美回答的字符 ?A 之间的区别之外,此代码还有一个隐藏但重要的故障。

您使用的递归不是尾部优化的,应该不惜一切代价避免这种情况。它通常可能导致堆栈溢出。以下是 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'

【讨论】:

    【解决方案2】:

    您可以使用? 代码点运算符:

      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] 匹配。

    【讨论】:

      猜你喜欢
      • 2023-03-21
      • 1970-01-01
      • 2012-06-24
      • 1970-01-01
      • 1970-01-01
      • 2019-02-01
      • 2011-10-04
      • 1970-01-01
      相关资源
      最近更新 更多