计划形式错误的特殊形式

时间:2012-01-26 22:41:48

标签: scheme

我是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))))

2 个答案:

答案 0 :(得分:2)

if表单由4部分组成:

  1. 单词if
  2. 条件。
  3. 当时的分支。
  4. 其他分支。
  5. 您的if - 表单由6部分组成。 (= (length original) 0)是条件。 left是then-branch,(append left (car original))是else-branch。但其他两个应该是什么?对于读者来说显而易见的是,他们仍然应该成为else分支的一部分,但编译器无法知道。就编译器而言,您可能也希望left(append left ...)进入then-branch,而其他两个进入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

答案 1 :(得分:2)

在开始之前,请尝试indent your programs properly。在这种情况下,它会使错误更加明显。

你正在遇到许多计划新手来自其他语言的速度爆炸:

Lisp中的

if(包括scheme)实际上是三元运算符,而不是来自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))))))