我是超级初学者。所以\xe2\x80\x99不要对我的问题这么简单感到惊讶。
\n我有以下清单(1 3 ((2))(7))
我必须用 function 重建该列表cons。
我不知道如何删除列表的第三个元素。
\n也许有人可以帮助我!
\n多谢!
\n(cons '1 (cons '3 (cons '(2) (cons '(7) nil))))\n --> (1 3 (2) (7))\nRun Code Online (Sandbox Code Playgroud)\n仍然缺少一些括号。我不知道修复它。
\n您的问题的解决方法如下:(请继续阅读,这不是最终答案)
(cons '1 (cons '3 (cons (cons '(2) nil) (cons '(7) nil))))
Run Code Online (Sandbox Code Playgroud)
你真的非常接近你的解决方案:(cons '1 (cons '3 (cons '(2) (cons '(7) nil))))问题是,正如你所说,2上缺少一些括号。你设法制作了(2)一个包含2的列表,但目标是制作一个,((2))这意味着:一个列表包含一个包含 2 的列表。所以我们简单地更改'(2) 为(cons '(2) nil)
现在,话虽这么说,我会认为使用 '(2) 是作弊,因为如果允许您使用引号,您可以只执行'(1 3 ((2)) (7))或等效操作(quote (1 3 ((2)) (7)))),然后就完成了。显然这不存在任何挑战。因此,您可能要做的就是仅使用 cons 而根本无法使用 quote,在这种情况下,解决方案将如下所示:
(cons 1 (cons 3 (cons (cons (cons 2 nil) nil) (cons (cons 7 nil) nil))))
Run Code Online (Sandbox Code Playgroud)
这更加纯粹,这可能就是你被分配做的事情,这将是一个有效的答案
我们甚至可以极端纯粹,将 nil 替换为()(它们都代表空列表),我们得到了这个
(cons 1 (cons 3 (cons (cons (cons 2 ()) ()) (cons (cons 7 ()) ()))))
Run Code Online (Sandbox Code Playgroud)
这真正体现了 lisp 的“一切皆列表”之美。但让我们面对现实吧,这太过分了
现在,如果仍有不清楚的地方,您可能需要更多地研究 lisp 中的列表到底是什么。我不是解释这一点的最佳人选(我是程序员,不是老师),但我可以尝试。我确实建议您自己做一些研究,即:
Cons 是 lisp 的基本构建块之一,它是一个非常非常简单的概念,它是一个容纳两个……东西的容器。这些东西是什么超出了我们需要了解的范围,但其本身就是一个非常有趣的话题。重要的一点是,我们可以像这样对两个事物(例如两个数字)调用 cons ,(cons 3 4)并且解释器会打印如下所示的内容(3 . 4),您可以通过调用获得第一个参数,通过如下car调用获得第二个参数:cdr
(car (cons 3 4)) ; 3
(cdr (cons 3 4)) ; 4
Run Code Online (Sandbox Code Playgroud)
好吧,我说 cons 可以保存东西,而不仅仅是数字,例如我们可以保存一个数字和空列表,NIL就像(cons nil 7)你所期望的那样(car (cons nil 7))确实返回NIL
我们还可以将一个缺点放在另一个缺点中!就像这样(cons (cons 3 4) (cons 6 7)),您可以将其想象为一棵具有多个分支的树(因此是一棵二叉树),每个分支也有两个分支,并且这些分支的末尾是保存每个数字的节点。我们仍然可以使用carandcdr来获取左侧和右侧元素(分别为(3 . 4)和(6 . 7))
好吧,就这么简单,有点太简单了,我们如何通过配对来获得列表呢?答案是抽象!计算机科学中有一个概念,称为链表。有很多方法可以用很多编程语言来实现它,通常使用指针之类的东西。链表背后的想法是,您可以将一系列事物编码为一系列节点,一个“节点”只不过是一个保存值的事物,以及获取下一个节点的一种方法。我们还需要对“没有下一个节点,您到达列表的末尾”的概念进行编码。如果您足够聪明,您可以开始了解各个部分是如何组合在一起的,并允许您仅使用 来构造一个链表cons。
如果我们想在 lisp 中创建一个数字链表(我简称为“列表”),我们可以使用 cons 定义节点。我们可以将数字作为第一个参数,将下一个节点作为第二个参数。我们还可以表示终止节点,它告诉我们我们处于列表的末尾且为 nil,因此如果下一个节点为 nil,则意味着我们到达了列表的末尾
无聊的例子是一个包含一个元素的列表,看起来像这样
(cons 8 nil)
Run Code Online (Sandbox Code Playgroud)
我们可以使用 获取此节点中的元素car,这将返回 8,并使用 获取下一个节点cdr。在这种情况下cdr将返回 NIL,它是终止节点,这将表明我们位于列表的最后一个节点
它不是很令人兴奋,但它是我们对链表进行建模所需的全部!现在让我们尝试创建一个包含两个元素的列表
(cons 8 (cons 9 nil))
Run Code Online (Sandbox Code Playgroud)
与之前的逻辑相同,我们可以获取第一个节点的值car,也可以获取下一个节点,通过cdr该节点将返回(cons 9 nil). 我们可以得到该节点的值car,它对应的下一个节点是终止符,我们到达了终点
事实上,如果您(cons 8 (cons 9 nil))在解释器中输入,您将得到与输入相同的结果(列表 8 9)。因为幕后的事情都是一样的
我们再举几个例子:
包含一个列表的列表怎么样?例如,我们学会了如何做,(8 9)但是呢((8 9))?
我们可以简单地将我们的整个(cons 8 (cons 9 nil))东西放入另一个节点(cons VALUE NEXT),其中 next 为 nil (没有下一个元素), value 为我们的整个列表,结果是:(cons (cons 8 (cons 9 nil)) nil)。事实上,解释器打印了((8 9))
有了这些知识,让我们再次尝试一下您的练习。但让我们更基本地了解它,我们可以看到它是一个由四个元素组成的列表(我们将它们称为a b c和d)。我们可以通过连接 4 个节点来列出它们:
(cons a
(cons b
(cons c
(cons d nil)
)
)
)
Run Code Online (Sandbox Code Playgroud)
现在让我们来谈谈a b c和d是什么。我们可以看出 a 和 be 只是数字,因此可以像这样很容易地替换它们
(cons 1
(cons 3
(cons c
(cons d nil)
)
)
)
Run Code Online (Sandbox Code Playgroud)
d也很简单,只是一个包含单个元素的列表,我们已经制作了其中一个,它看起来像这样,(const 7 nil)所以我们也可以替换它
(cons 1
(cons 3
(cons c
(cons (cons 7 nil) nil)
)
)
)
Run Code Online (Sandbox Code Playgroud)
最后c是最复杂的一个,因为它是一个包含列表的列表,但我们可以处理这个没问题,我们只需创建一个单个元素的列表,(cons VALUE nil)然后将值替换为另一个单个元素的列表(cons 2 nil),然后用它替换值,这样我们得到(cons (cons 2 nil) nil)。我们可以在最终答案中替换它以获得:
(cons 1
(cons 3
(cons (cons (cons 2 nil) nil)
(cons (cons 7 nil) nil)
)
)
)
Run Code Online (Sandbox Code Playgroud)
或者返回一行:
(cons 1 (cons 3 (cons (cons (cons 2 nil) nil) (cons (cons 7 nil) nil) )))
Run Code Online (Sandbox Code Playgroud)
我们开始吧!你现在可能已经明白了,这是一个非常简单的概念,但它有很多含义,这需要一段时间才能理解,当你最终做到这一点时,你会一睹 Lisp 编程语言的终极力量
我们可以编写一个程序来做到这一点。
CL-USER 85 > (defun consify (expression)
(cond ((atom expression)
(typecase expression
(null expression)
(symbol (list 'quote expression))
(otherwise expression)))
(t
(list 'cons
(consify (first expression))
(consify (rest expression))))))
CONSIFY
Run Code Online (Sandbox Code Playgroud)
上面返回 CONS 表达式。
CL-USER 86 > (consify '(1 3 ((2))(7)))
(CONS 1 (CONS 3 (CONS (CONS (CONS 2 NIL) NIL) (CONS (CONS 7 NIL) NIL))))
Run Code Online (Sandbox Code Playgroud)
我们现在可以评估上面的结果:
CL-USER 87 > (eval (consify '(1 3 ((2))(7))))
(1 3 ((2)) (7))
Run Code Online (Sandbox Code Playgroud)
与你的其他表达方式相同:
CL-USER 88 > (pprint (consify '((Fat Cat)
(In da ((House)) It)
(Might eat (the (treats))))))
(CONS (CONS 'FAT (CONS 'CAT NIL))
(CONS (CONS 'IN (CONS 'DA (CONS (CONS (CONS 'HOUSE NIL) NIL)
(CONS 'IT NIL))))
(CONS (CONS 'MIGHT
(CONS 'EAT (CONS (CONS 'THE
(CONS (CONS 'TREATS NIL)
NIL))
NIL)))
NIL)))
CL-USER 89 > (eval (consify '((Fat Cat)
(In da ((House)) It)
(Might eat (the (treats))))))
((FAT CAT) (IN DA ((HOUSE)) IT) (MIGHT EAT (THE (TREATS))))
Run Code Online (Sandbox Code Playgroud)