【问题标题】:Appending undefined to a list将未定义附加到列表
【发布时间】:2013-02-04 07:59:08
【问题描述】:

我正在调试一个错误,发现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中列表的底层实现有关吗?

【问题讨论】:

  • 因此与#erlang@freenode 的几个伙伴讨论了这个问题。这是一个“不当列表”的例子。它有几个好处。考虑一个元组:{key, value}。在 erlang VM 内部,这是三个术语。一个术语是二元素元组,另外两个是术语keyvalue。访问元组时,您必须首先取消引用元组术语以访问它包含的两个术语。但是,假设我们将其实现为不正确的列表:[key|value]。使用这种格式,您不必取消对术语的引用,并且可以节省内存(因为您也不必存储元组术语)。
  • 之所以有效,是因为 Erlang 列表是 CONS 列表,这意味着列表的每个单元格都是两个单词对,相当于 struct list_cell {Eterm hd; Eterm tl;}[a|b] 创建一个 list_cell,hd 设置为原子 a,tl 设置为原子 b。还应该注意的是,iolists 可能(并且合法/合理地)是不适当的列表。
  • 听起来正确。以下是一些解释不当列表及其用途的链接:stackoverflow.com/questions/1919097/…stackoverflow.com/questions/5088575/…

标签: list erlang


【解决方案1】:

在 Erlang 中,所有术语都由一个紧凑的类似指针的值表示,称为 Eterm。列表操作函数似乎与类型无关。

从这个角度考虑:在 erlang VM 内部,所有 Eterm 都是平等的。头部和尾部列表操作操作被称为非常快。既然要评估不透明的Eterm 类型来确定它是否是一个列表需要多次操作,那何必呢?

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

对于信任程序员有一点要说,当处理一个增加了几个周期并经常使用的操作时,忽略一个错误的附加的潜在好处会累积起来,唯一的惩罚是一个奇怪的错误。

【讨论】:

  • 我知道这一点。我的问题是:为什么[1,2,3] ++ undefined 不会崩溃?
  • 是的,对不起,误读了您的问题。用我的最佳猜测更新了我的答案,但我不知道确切的答案。
  • @Isac:想知道一些有趣的事情吗?它似乎发生在任何数据类型上。我用不同的原子、整数和浮点数进行了尝试。没有人抱怨操作,后来都没有阅读列表。
  • 这很奇怪。我更新了我的最佳猜测答案;我认为很有可能。
  • 我已更改为对 rvirding 的正确答案,因为它更完整且更具指导性。对不起汤。感谢所有的帮助!
【解决方案2】:

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

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"?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-03
    • 1970-01-01
    • 1970-01-01
    • 2021-11-13
    • 1970-01-01
    • 2018-02-04
    • 1970-01-01
    相关资源
    最近更新 更多