将undefined追加到列表中

时间:2013-02-19 15:14:37

标签: list erlang

我正在调试错误,发现undefined已被附加到列表中,导致稍后崩溃。

我预计使用++运算符追加列表以外的内容会导致崩溃。但undefined并非如此。这是一个例子:

1> [1,2,3] ++ undefined.
[1,2,3|undefined]

虽然它没有崩溃,但列表不再具有完整功能:

1> L = [1,2,3] ++ undefined.
[1,2,3|undefined]
2> L ++ [4].
** exception error: bad argument
     in operator  ++/2
        called as [1,2,3|undefined] ++ [4]

为什么会这样? 这与erlang中列表的底层实现有关吗?

2 个答案:

答案 0 :(得分:1)

在Erlang中,所有术语都由称为Eterm的类似指针的紧凑值表示。似乎列表操作函数实现为类型不可知。

从这个角度考虑:在erlang VM中,所有Eterms都是相同的。头部和尾部列表操作操作被称为非常快。由于需要多次操作来评估不透明Eterm类型以确定它是否是列表,为什么还要麻烦?

在这种情况下的预期结果是错误,你确实得到了一个错误。最终

有一些东西可以说是信任程序员,当处理一个增加了几个循环并经常使用的操作时,忽略一个坏的追加的潜在好处就会堆积起来,唯一的惩罚是一个奇怪的错误。

答案 1 :(得分:1)

原因是++将第二个参数附加到第一个参数的末尾,必须是一个列表。它没有对第二个参数进行任何处理,它只是按原样附加它。所以:

1> [1,2,3] ++ undefined.
[1,2,3|undefined]
2> [1,2,3] ++ [undefined].
[1,2,3,undefined]

你可以这样做的原因:

3> [a|b].
[a|b]
4> [a|[b]].
[a,b]

是列表是序列列表单元格,单链表,而不是单个数据结构。如果每个单元格的右侧(称为 tail )是另一个列表单元格或[],那么您将获得正确的列表。每个单元格的左侧称为 head ,通常包含列表的元素。这就是我们在上面的2和4中所拥有的。大多数(如果不是全部)库函数都假定列表是正确的列表,如果不是,则会生成错误。请注意,您必须将整个列表逐步降低到最后才能查看它是否正确。

每个列表单元格都写为[Head|Tail],语法[a,b,c]只是[a|[b|[c|[]]]]的语法糖。请注意,每个列表单元格的尾部都是一个列表或[],因此这是一个正确的列表。

列表单元格的头部和尾部的类型没有限制。系统从不检查它只是做它。这就是我们在上面的1和3中所用的最后一个列表单元格的尾部(仅列出3中的单元格)不是列表或[]

抱歉在这里得到一些过分教育。

编辑:我看到我已在此处对此进行了描述:Functional Programming: what is an "improper list"?