安全地连接长生不老药列表?

Safely concatenate elixir list?

如何nil在 Elixir 中安全地连接列表?

我已经用 ++

提供了一些情况和响应的内联示例

看起来 nil 在连接时被视为一个特殊的实体。

为什么会这样?

# Append two empty list ✅
iex(1)> [] ++ []
[]
# Append empty list to nil ❌
iex(2)> [] ++ nil
nil # Result should be []
# Append non empty list to nil ❌
iex(3)> [1] ++ nil
[1 | nil] # Result should be [1]
# Append non empty list to nil and enumerate ❌
iex(5)> a = [1, 2] ++ nil
[1, 2 | nil]
iex(6)> Enum.each(a, fn p -> IO.puts(p) end)
1
2
** (FunctionClauseError) no function clause matching in Enum."-each/2-lists^foreach/1-0-"/2
# Add more lists with nil ❌
iex(5)> [1, 2] ++ nil ++ []
** (ArgumentError) argument error

您发现了不正确的列表:最后一个元素的尾部不是空列表的列表。 List documentation:

中有一个很好的例子

正则列表(相当于[1, 2, 3]):

[1 | [2 | [3 | []]]]

不正确的列表(相当于[1, 2 | 3]):

[1 | [2 | 3]]

nil 没有什么特别之处 - 任何非列表都会发生同样的事情:

iex(1)> [1, 2] ++ "foo"
[1, 2 | "foo"]
iex(2)> [1, 2] ++ %{3 => 4}
[1, 2 | %{3 => 4}]
iex(3)> Enum.each([1,2|"boom"], &IO.puts(&1))
1
2
** (FunctionClauseError) no function clause matching in Enum."-each/2-lists^foreach/1-0-"/

来自 documentation for ++:

List concatenation operator. Concatenates a proper list and a term, returning a list.

If the right operand is not a proper list, it returns an improper list. If the left operand is not a proper list, it raises ArgumentError.

来自 Enum.each 的错误很奇怪,但它似乎也是由期望正确列表的实现引起的。

我认为这回答了您的问题,但我怀疑它没有解决您的问题。您没有提到 为什么 您要将 nil 附加到列表,也没有提到您要实现的目标。

我相信你想找回一个正常的、正确的列表。为此,调用 ++/2 的两个参数都必须是列表。

您可能在 List.wrap/1 之后 nil

iex|1 ▸ [] ++ List.wrap([])
#⇒ []
iex|2 ▸ [] ++ List.wrap(nil)
#⇒ []
iex|3 ▸ [1] ++ List.wrap(nil)
#⇒ [1]
iex|4 ▸ [1, 2] ++ List.wrap(nil)
#⇒ [1, 2]
iex|5 ▸ [1, 2] ++ List.wrap(nil) ++ [3]
#⇒ [1, 2, 3]
iex|6 ▸ [1] ++ List.wrap(2)            
#⇒ [1, 2]

如果你想消除nil部分,那么你可以使用模式匹配。例如:

defmodule Example do
  def add(list1, list2) do
    case [list1, list2] do
      [nil, nil] -> []
      [nil, list2] -> list2
      [list1, nil] -> list1
      [list1, list2] -> list1 ++ list2
    end
  end
end