: erlang.bit_size (nil) ошибка, когда первый аргумент в функции равен нулю - PullRequest
0 голосов
/ 01 июня 2018
defmodule Complex do
    def complex_to_string(r, i) do
        to_str = ""
        to_str = to_str <>
        if r != 0 do
            "#{r}"
        end

        to_str = to_str <>
        cond do
            i < 0 or (r == 0 and i != 0) ->
                "#{i}i"
            i > 0 ->
                "+#{i}i"
            :true ->
                ""
        end
        to_str
    end
end

Все отлично работает, когда первый аргумент не равен нулю.

iex(111)> Complex.complex_to_string(-1, 4)
"-1+4i"
iex(109)> Complex.complex_to_string(4, 2)
"4+2i"
iex(110)> Complex.complex_to_string(4, 0)
"4"

После вызова функции с нулем в качестве первого параметра возникает ошибка.

iex(111)> Complex.complex_to_string(0, 4)

** (ArgumentError) ошибка аргумента: erlang.bit_size(nil) iex: 111: Complex.complex_to_string / 2

Почему это происходит?Можно ли вызвать функцию с первым параметром в качестве нуля?Если нет, то почему?

Редактировать 1:

После быстрого анализа мне удалось решить эту проблему.Проблема заключалась в том, что if r == 0 тогда to_str <> nil произойдет. Не было опции по умолчанию (иначе) для условной инструкции .

    to_str = to_str <>
    cond do 
        r != 0 -> 
            "#{r}"
        true ->
            ""
    end

Это решает проблему.

Ответы [ 2 ]

0 голосов
/ 01 июня 2018

Хотя с ответом @ Dogbert это работает, весь код очень противоречит идиоматике.В эликсире мы в основном используем сопоставление вместо спагетти if с.Всегда лучше обрабатывать угловые случаи явно:

defmodule Complex do
  def complex_to_string(r, i)
    when not is_number(r) or not is_number(i),
    do: raise "Unexpected input"

  # added for clarity, (r, 0) covers the case
  def complex_to_string(0, 0), do: "0"

  def complex_to_string(r, 0), do: "#{r}"
  def complex_to_string(0, i), do: "#{i}i"
  def complex_to_string(r, i)
    when i > 0, do: "#{r}+#{i}i"
  # guard below is redundant, added for clarity
  def complex_to_string(r, i)
    when i < 0, do: "#{r}#{i}i"
end

[{-1,5},{2,0},{0,-2},{0,0},{-3,-3}]
|> Enum.map(fn {r, i} ->
     Complex.complex_to_string(r, i)
   end)
#⇒ ["-1+5i", "2", "-2i", "0", "-3-3i"]
0 голосов
/ 01 июня 2018

Проблема в этой строке:

to_str = to_str <>
  if r != 0 do
    "#{r}"
  end

Когда r == 0, if возвращает nil (потому что нет блока else), который не может быть добавлен кСтрока.Если вы не хотите добавлять что-либо, если r == 0, верните "" из else:

to_str = to_str <>
  if r != 0 do
    "#{r}"
  else
    ""
  end

или короче:

to_str = to_str <> if(r != 0, do: "#{r}", else: "")
...