简体   繁体   English

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

[英]Why can't I use car inside this let statement in Scheme?

The following Scheme code works fine:以下方案代码工作正常:

(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)))

It is supposed to output a list with the first element being an integer x and the subsequent elements being all the integers from numbers-input which have the same parity as x.它应该是 output 一个列表,其中第一个元素是 integer x,后续元素是来自 numbers-input 的所有整数,其奇偶性与 x 相同。

If anyone is interested, this is my attempt at solving the exercise 2.20 from the book Structure and Interpretation of Computer Programs .如果有人感兴趣,这是我尝试解决《 计算机程序的结构和解释》一书中的练习 2.20。

Now, I wanted to replace (car numbers-left) and (cdr numbers-left) with the variables "first" and "rest".现在,我想用变量“first”和“rest”替换 (car numbers-left) 和 (cdr numbers-left)。

(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)))

Trying to call this function now gives me an error:尝试调用此 function 现在给我一个错误:

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

Racket is highlighting the (car numbers-left) inside of the let-statement. Racket 突出显示了 let 语句中的(左车号)。 Even when I never actually call "first" or "rest" in the body of the function and just leave it the way it was before, I get the same error.即使我从未真正在 function 的主体中调用“第一个”或“休息”并保持原来的样子,我也会遇到同样的错误。

However, in the following code I tried to copy the structure of the above procedure in a simple test definition and surprisingly, this works as you would expect.然而,在下面的代码中,我试图在一个简单的测试定义中复制上述过程的结构,令人惊讶的是,这正如你所期望的那样工作。

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

> (test 1 2 3 4 5)
2

It turns out that if I replace my (cond...) in my original program with a simple call it works fine as well, so somehow the (cond...) statement prohibits me from using the variables.事实证明,如果我用一个简单的调用替换原始程序中的 (cond...) ,它也可以正常工作,因此 (cond...) 语句以某种方式禁止我使用变量。

I know this is a very specific thing and I don't know if this ever really matters (except maybe if you want to make the code more readable) but I would really like to know why exactly it behaves this way.我知道这是一件非常具体的事情,我不知道这是否真的很重要(除非你想让代码更具可读性),但我真的很想知道它为什么会这样。

Any insight would be appreciated!任何见解将不胜感激!

Variables' values are evaluated as soon as you define them, whether you use them or not.变量的值在您定义它们后立即进行评估,无论您是否使用它们。 Therefore you are calling (car '()) at the end of your recursion, once the list has become empty.因此,一旦列表变为空,您将在递归结束时调用(car '()) You never make it to the part of your cond that attempts to exit.您永远不会到达尝试退出的cond部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM