格式错误的特殊形式

问题描述 投票:2回答:2

我对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))))
scheme
2个回答
3
投票

开始之前,请尝试进行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))))))

2
投票

if表格由4部分组成:

  1. if
  2. 条件。
  3. 当时的分支。
  4. 其他分支。

您的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

© www.soinside.com 2019 - 2024. All rights reserved.