jld*_*ont 44 lisp erlang scheme functional-programming
有人可以解释什么是"不正确的清单"吗?
注意:谢谢大家!你们所有人摇滚!
rvi*_*ing 63
我认为@Vijay的答案是迄今为止最好的答案,我只是打算将其Erlangify.
Erlang中的对(cons单元格)写成,[Head|Tail]而nil写成[].关于头部和尾部是什么没有限制,但如果你使用尾部链接更多的cons细胞,你会得到一个列表.如果最后的尾巴是[]你得到一个正确的列表.正确列表中的列表有特殊的语法支持
[1|[2|[3|[]]]]
Run Code Online (Sandbox Code Playgroud)
写成
[1,2,3]
Run Code Online (Sandbox Code Playgroud)
和不正确的清单
[1|[2|[3|4]]]
Run Code Online (Sandbox Code Playgroud)
写成
[1,2,3|4]
Run Code Online (Sandbox Code Playgroud)
所以你可以看到差异.匹配正确/不正确的列表相应容易.所以len适当列表的长度函数:
len([_|T]) -> 1 + len(T);
len([]) -> 0.
Run Code Online (Sandbox Code Playgroud)
我们明确匹配终止的地方[].如果给出不正确的列表,则会产生错误.last_tail返回列表最后一个尾部的函数也可以处理不正确的列表:
last_tail([_|T]) -> last_tail(T);
last_tail(Tail) -> Tail. %Will match any tail
Run Code Online (Sandbox Code Playgroud)
需要注意的是建立一个列表,或反对它的匹配,你通常用做[Head|Tail]并不能检查,如果尾巴名单所以在处理不当的名单没有问题.虽然你可以用它们做很酷的事情,但很少需要不正确的列表.
Vij*_*hew 40
我认为使用Scheme解释这个更容易.
列表是一对以空列表结尾的对.换句话说,列表以cdr为()的对结束
(a . (b . (c . (d . (e . ())))))
;; same as
(a b c d e)
Run Code Online (Sandbox Code Playgroud)
不以空列表结尾的一对对称称为不正确列表.请注意,不正确的列表不是列表.列表和点缀符号可以组合以表示不正确的列表,如以下等效符号所示:
(a b c . d)
(a . (b . (c . d)))
Run Code Online (Sandbox Code Playgroud)
导致构建不正确列表的常见错误的示例是:
scheme> (cons 1 (cons 2 3))
(1 2 . 3)
Run Code Online (Sandbox Code Playgroud)
注意(1 2 .3)中的点---就像(2.3)中的点一样,说一对的cdr指向3,而不是另一对或'().也就是说,它是一个不合适的列表,而不仅仅是一对列表.它不适合列表的递归定义,因为当我们到达第二对时,它的cdr不是列表 - 它是一个整数.
Scheme打印出列表的第一部分,好像它是一个普通的cdr链表,但是当它到达终点时,它不能那样做,所以它使用了"点表示法".
你通常不需要担心点符号,因为你应该使用普通列表,而不是不正确的列表.但是如果你在Scheme打印出一个数据结构时看到一个意想不到的点,那么你很好地猜测你使用了cons并给它一个非列表作为它的第二个参数 - 除了另一个对或()之外的东西.
Scheme提供了一个方便的过程,可以创建适当的列表,称为列表.list可以接受任意数量的参数,并按照该顺序构造包含这些元素的正确列表.您不必记住提供空列表---列表会自动终止列表.
Scheme>(list 1 2 3 4)
(1 2 3 4)
Run Code Online (Sandbox Code Playgroud)
礼貌:计划简介
Gor*_*rie 10
Erlang中列表的定义在手册中给出- 特别是第2.10节
在Erlang中,你真正需要知道的关于不正确列表的唯一方法是如何避免它们,并且这样做的方法非常简单 - 这完全取决于你要构建列表的第一个"事物".以下都创建了正确的列表:
A = [].
B = [term()].
C = [term(), term(), term()].
Run Code Online (Sandbox Code Playgroud)
在所有这些情况下,语法确保有一个隐藏的"空"尾部,它与最后的"[]" 类型匹配....
所以从他们那里以下操作都产生了一个合适的列表:
X = [term() | A].
Y = [term() | B].
Z = [term() | C].
Run Code Online (Sandbox Code Playgroud)
它们都是为正确的列表添加新头的所有操作.
有用的是你可以提供每个X,Y或者Z像这样的函数:
func([], Acc) -> Acc;
func([H | T], Acc) -> NewAcc = do_something(H),
func(T, [NewAcc | Acc]).
Run Code Online (Sandbox Code Playgroud)
当尾部的隐藏空列表全部留下时,它们将遍历列表并终止于顶部子句.
当您的基本列表制作不当时会出现问题,如下所示:
D = [term1() | term2()]. % term2() is any term except a list
Run Code Online (Sandbox Code Playgroud)
此列表不具备隐藏空列表为终端的尾巴,它有一个长期...
那你怎么为它写一个终端条款呢?
让它真气的是,通过检查它是无法查看列表是否不合适...打印该死的东西看起来不错......所以你最终创建了一个不合适的基础列表,做了一些东西,传递它,然后突然kabloowie你有一个英里从错误的地方崩溃,你拉你的头发,尖叫和喊...
但你应该用透析器为你嗅出这些小动物.
按照罗伯特的评论,我试着打印出一个不合适的清单,而且,很明显:
(arrian@localhost)5>A = [1, 2, 3, 4].
[1,2,3,4]
(arrian@localhost)5> B = [1, 2, 3 | 4].
[1,2,3|4]
(arrian@localhost)6> io:format("A is ~p~nB is ~p~n", [A, B]).
A is [1,2,3,4]
B is [1,2,3|4]
Run Code Online (Sandbox Code Playgroud)
我花了一些时间寻找一个不正确的列表一次,确信自己是invsible,以及阿肯野应!
要了解不正确的列表是什么,您必须首先了解正确列表的定义.
具体来说,列表的"整洁发现"是您可以仅使用具有固定数量元素的表单来表示列表,即:
;; a list is either
;; - empty, or
;; - (cons v l), where v is a value and l is a list.
Run Code Online (Sandbox Code Playgroud)
这个"数据定义"(使用如何设计程序的术语)具有各种不错的属性.最好的一点是,如果我们在数据定义的每个"分支"上定义函数的行为或含义,我们保证不会错过一个案例.更重要的是,像这样的结构通常会产生漂亮干净的递归解决方案.
经典的"长度"示例:
(define (length l)
(cond [(empty? l) 0]
[else (+ 1 (length (rest l))]))
Run Code Online (Sandbox Code Playgroud)
当然,在Haskell中一切都比较漂亮:
length [] = 0
length (f:r) = 1 + length r
Run Code Online (Sandbox Code Playgroud)
那么,这与不正确的列表有什么关系呢?
好吧,一个不正确的列表使用这个数据定义,而是:
;; an improper list is either
;; - a value, or
;; - (cons v l), where v is a value and l is an improper list
Run Code Online (Sandbox Code Playgroud)
问题是这个定义导致模棱两可.特别是,第一和第二种情况重叠.假设我为不正确的列表定义"长度":
(define (length l)
(cond [(cons? l) (+ 1 (length (rest l)))]
[else 1]))
Run Code Online (Sandbox Code Playgroud)
问题是我已经破坏了很好的属性,如果我取两个值并将它们放入一个不正确的列表中(cons ab),结果的长度为2.为了理解原因,假设我考虑了值(cons 3 4)和(cons 4 5).其结果是(利弊(利弊3 4)(利弊4 5)),其可被解释或者为包含不当列表(利弊3 4)和(利弊4 5),或作为包含不当列表(利弊3 4) ,4和5.
在具有更严格类型系统的语言(例如Haskell)中,"不正确列表"的概念并没有那么多意义; 您可以将其解释为一种数据类型,其基本情况中包含两个内容,这可能不是您想要的.