:函数中的第一个参数为零时,erlang.bit_size(nil)错误

时间:2018-05-31 22:13:28

标签: erlang elixir

import seaborn as sns
sns.set_style("whitegrid")
tips = sns.load_dataset("tips")
ax = sns.barplot(x="day", y="total_bill", data=tips) 
ax.text( -0.1, 10, '1', fontsize=24)
ax.text(1-0.1, 10, '2', fontsize=24)
ax.text(2-0.1, 10, '3', fontsize=24)
ax.text(3-0.1, 10, '4', fontsize=24)

当第一个参数不为零时,一切正常。

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"

  

**(ArgumentError)参数错误       :erlang.bit_size(无)       iex:111:Complex.complex_to_string / 2

为什么会这样?是否可以调用第一个参数为零的函数?如果不是那么为什么?

编辑1:

经过快速分析后,我设法解决了这个问题。问题是iex(111)> Complex.complex_to_string(0, 4)然后if r == 0会发生。 条件指令没有默认选项(否则)

to_str <> nil

这解决了这个问题。

2 个答案:

答案 0 :(得分:3)

虽然@ Dogbert的回答是有效的,但整个代码都是反惯用的。在Elixir中,我们主要使用模式匹配而不是意大利面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"]

答案 1 :(得分:2)

问题出在这一行:

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: "")