Lisp 组合DrRacket隐式else

Lisp 组合DrRacket隐式else,lisp,racket,Lisp,Racket,为什么这样做有效 (define (rev l) (cond ((null? l) l) (else (append (rev(cdr l)) (list (car l)))))) 输出: > (rev L1) (d c b a) > (rev L1) (a) 这不是吗 (define (rev l) (cond ((null? l) l) (append (rev(cdr l)) (list (car l))))) 输出: > (rev

为什么这样做有效

(define (rev l)
  (cond ((null? l) l)
        (else (append (rev(cdr l)) (list (car l))))))
输出:

> (rev L1)
(d c b a)
> (rev L1)
(a)
这不是吗

(define (rev l)
  (cond ((null? l) l)
    (append (rev(cdr l)) (list (car l)))))
输出:

> (rev L1)
(d c b a)
> (rev L1)
(a)

在第二个示例中,过程append是谓词,因为它是一个过程,除f外的每个值都是true,所以它会执行后续的rev cdr l

cond的术语必须放在括号中。没有显式的else,如果两个谓词都不匹配,则实现可以选择结果未定义的值

if是一个不同的条件,可能更适合这种情况

(define (rev l)
  (if (null? l)
      l
      (append (rev (cdr l))
              (list (car l))))) 

更改缩进可以更容易地查看发生了什么:

(define (rev l)
  (cond
    [(null? l)  l]
    [else       (append (rev(cdr l)) (list (car l)))]))

(define (rev l)
  (cond
    [(null? l)  l]
    [append     (rev(cdr l))
                (list (car l))]))
注意,在第二个版本中有一个子句

    [append     (rev(cdr l))
                (list (car l))]))
当计算cond表达式时,它会尝试计算每个左侧,直到找到一个给出非false值的表达式。这里,左侧的append计算为append函数,它是一个非false值

接下来发生的事情是对右侧进行评估。由于右侧有一个隐式开始,因此将对其进行计算:

              (begin
                (rev(cdr l))
                (list (car l)))
总结:您意外地编写了一个语法正确的表达式,但其含义与您预期的不同

请注意,如果在cond中的子句周围使用方括号,则更容易发现错误。方括号[]和标准的含义相同