为什么我不能在Scheme的let语句内使用car?

问题描述 投票:0回答:1

以下计划代码可以正常工作:

(define (same-parity x . numbers-input)
  (define (check-parity a) (= (remainder x 2) (remainder a 2)))
  (define (iter numbers-left)
    (cond ((null? numbers-left) nil)
          ((check-parity (car numbers-left)) (cons (car numbers-left) (iter (cdr numbers-left))))
          (else (iter (cdr numbers-left))))) 
  (cons x (iter numbers-input)))

应该输出一个列表,第一个元素是整数x,随后的元素是数字输入中所有与x奇偶性相同的整数。

[如果有人感兴趣,这是我尝试解决本书Structure and Interpretation of Computer Programs中的练习2.20。

现在,我想用变量“ first”和“ rest”替换(左车号)和(cdr左号)。

(define (same-parity x . numbers-input)
  (define (check-parity a) (= (remainder x 2) (remainder a 2)))
  (define (iter numbers-left)
    (let ((first (car numbers-left))
          (rest (cdr numbers-left)))
      (cond ((null? numbers-left) nil)
            ((check-parity first) (cons first (iter rest)))
            (else (iter rest))))) 
  (cons x (iter numbers-input)))

现在尝试调用此函数给我一个错误:

> (same-parity 1 2 3 4 5)
. . mcar: contract violation
  expected: mpair?
  given: ()

球拍突出显示了let语句内的(左车号)。即使我从未真正在函数主体中调用“ first”或“ rest”,而只是将其保留为以前的样子,我也会遇到相同的错误。

但是,在下面的代码中,我试图在一个简单的测试定义中复制上述过程的结构,而且令人惊讶的是,此过程如您所愿。

(define (test x . testlist)
  (define (test2 test2list)
    (let ((first (car test2list)))
      first))
  (test2 testlist))

> (test 1 2 3 4 5)
2

事实证明,如果我用一个简单的调用替换原始程序中的(cond ...),它也可以正常工作,因此(cond ...)语句会禁止我使用变量。

[我知道这是非常具体的事情,我不知道这是否真的很重要(除非您是否想使代码更具可读性,但我真的很想知道为什么它会以这种方式工作。

任何见识将不胜感激!

list scheme racket sicp cons
1个回答
0
投票
© www.soinside.com 2019 - 2024. All rights reserved.