我对Scheme非常陌生,尝试使用此功能时遇到“格式错误的特殊形式”错误。如果原始的长度为0,我希望函数返回left。否则,我希望它执行附加的调用和递归调用。我想我可能做的很愚蠢,导致了这种情况。有帮助吗?
(define (partition left right original)
(if (= (length original) 0) left
(append left (car original))
(append right (car (reverse original)))
(partition left right (reverse original))))
开始之前,请尝试进行indent your programs properly。在这种情况下,它会使错误更加明显。
[您遇到了许多Scheme新手来自其他语言的冲击:
Lisp(包括方案)中的[if
实际上是三元运算符,而不是类似C的世界中的if
块。
您的代码尝试用三种以上形式显示if
,因此失败。天真的,您可以做的是使用块构造begin
(在Common Lisp中为progn
),以确保条件的单个分支仅包含单个形式。
(define (partition left right original)
(if (= (length original) 0)
left
(begin
(append left (car original))
(append right (car (reverse original)))
(partition left right (reverse original)))))
现在,我感觉到它也不会做您想要的事情,因为append
是有功能的(也就是说,它返回的结果没有修改其参数)。换句话说,您对append
的调用都不会执行任何操作,并且original
永远不会变短。您实际上想要的是类似
(define (partition left right original)
(if (= (length original) 0)
left
(partition (cons (car original) left)
(cons (last original) right)
(cdr (take original (- (length original) 1))))))
if
表格由4部分组成:
if
。您的if
表格由6部分组成。条件为(= (length original) 0)
。 left
是然后分支,(append left (car original))
是else分支。但是其他两个应该是什么?对于读者来说,很明显,它们仍然应该是else分支的一部分,但是编译器无法知道。据编译器知道,您可能同样希望将left
和(append left ...)
放在then分支中,而将另外两个放在else
分支中。
如果要在if
中执行多个表达式,则需要某种方式将属于同一分支的表达式分组在一起。您可以使用begin
这样操作:
(if condition
(begin
(do-something-in-the-then-branch)
(do-something-else-in-the-then-branch))
(begin
(do-something-in-the-else-branch)
(do-something-else-in-the-else-branch)))
但是,在您的情况下,这实际上无济于事,因为append
无法就地工作。即如果您执行(append left (car original))
,则left
的值实际上不会更改。取而代之的是append
将返回一个包含left
和(car original)
内容的新列表,而实际上没有更改任何一个列表。因此,要利用append
的结果,您需要使用其返回值。
因此,为了使函数正常工作,您应该将调用直接作为参数追加到partition
上,或者使用let
将结果分配给变量,然后将变量传递给partition
。