Scheme 是否可以在if/cond内使用let?

Scheme 是否可以在if/cond内使用let?,scheme,lisp,racket,sicp,Scheme,Lisp,Racket,Sicp,我经常发现自己想要处理列表中的当前元素,而不必总是对其运行一个过程来获取它,例如,每当我想引用序列中的当前元素时,使用elem,而不是(car sequence)。这是有效的…除非序列为空,因此我不能将let置于null检查之前。以下是我尝试的“模式”: (define (filter sequence) ; return a list of only those items where the filter predicate returns true (cond ((null? se

我经常发现自己想要处理列表中的当前元素,而不必总是对其运行一个过程来获取它,例如,每当我想引用序列中的当前元素时,使用
elem
,而不是
(car sequence)
。这是有效的…除非序列为空,因此我不能将
let
置于
null
检查之前。以下是我尝试的“模式”:

(define (filter sequence)
  ; return a list of only those items where the filter predicate returns true
  (cond ((null? sequence) nil)
        ; now that we know we have an active sequence, I want to short-hand 'elem' and 'rest'
        (let (elem car sequence) 
              (rest cdr sequence))
          (display elem)))
但是我得到一个错误,说
let:bad syntax
。有没有一种方法可以实现上述模式

Upate:也许最好的方法就是在顶部抛出一个
let
,然后进行一个简单的
if
检查?比如:

(define (filter sequence)
  (let ((elem (if (null? sequence) nil (car sequence)))
       (rest (cdr sequence)))
    (cond ((null? sequence) nil)
          (display elem))))
  

一种很有技巧的方法是将
let
放在顶部——在条件前面,并添加
if
检查每个
let
变量,例如:

(define (filter test sequence)
  (let ((elem (if (null? sequence) nil (car sequence)))
        (rest (if (null? sequence) nil (cdr sequence))))
    (cond ((null? sequence) nil)
          ((test elem) (cons elem (filter test rest)))
          (else (filter test rest)))))

第一个代码段的括号格式不正确。在此处使用
if
而不是
cond
,可以按如下方式进行修复:

(define (filter sequence)
  ; return a list of only those items where the 
  ; filter predicate returns true
  (if (null? sequence) 
      'nil
      ; now that we know we have an active sequence, 
      ; I want to short-hand 'elem' and 'rest'
      (let ((elem (car sequence)) 
            (rest (cdr sequence)))
        (display elem)
        (filter rest))))

还要注意,我递归调用
filter
。您还需要修改它,以接受谓词参数并实际过滤元素。

[这是我昨晚开始编写的coredump答案(我认为是正确答案)的附录,因此我将留给后代。]

从代码开始:

(define (filter sequence)
  (cond ((null? sequence) nil)
        (let (elem car sequence) 
              (rest cdr sequence))
          (display elem)))
这里至少有三个问题:首先,你搞错了
cond
的语法,这是(部分)

现在的问题是(由于某种原因,这个问题产生的错误掩盖了
cond
中的错误)您弄错了
let
的语法,这是(再次,部分):

现在我们得到了最后的错误:对
car
cdr
的调用没有任何限制。因此,解决这些问题:

(define (filter sequence)
  (cond ((null? sequence) nil)
        (else
         (let ((elem car sequence)
               (rest cdr sequence))
           (display elem)))))
(define (filter sequence)
  (cond ((null? sequence) nil)
        (else
         (let ((elem car sequence)
               (rest cdr sequence))
         (display elem))))
好吧,现在这还不正确,那是因为你错过了对
car
cdr
的调用:

(define (filter sequence)
  (cond ((null? sequence) nil)
        (else
         (let ((elem (car sequence))
               (rest (cdr sequence)))
           (display elem)))))
这现在起作用了,但实际上并没有过滤序列。为此,它需要递归:

(define (filter sequence)
  (cond ((null? sequence) nil)
        (else
         (let ((elem (car sequence))
               (rest (cdr sequence)))
           (if (null? elem)
               (filter rest)
               (cons elem (filter rest)))))))
将内部条件提升为
条件可能更好:

(define (filter sequence)
  (cond ((null? sequence) nil)
        ((null (car sequence)) (filter (cdr sequence)))
        (else (cons (car sequence) (filter (cdr sequence))))))
虽然现在您遇到了多次调用
car
cdr
的问题,但我认为您希望避免这种情况

如果使用full Racket,一个很好的表达方式是使用匹配,它可以很好地将检查和绑定结合起来:

(define (filter sequence)
  (match sequence
    ['() '()]
    [(cons '() tail)
     (filter tail)]
    [(cons head tail)
     (cons head (filter tail))]))

你的方法是正确的,但是你的括号是错的binding@coredump下面的答案看起来合适吗?你也应该看到。
(define (filter sequence)
  (cond ((null? sequence) nil)
        (else
         (let ((elem (car sequence))
               (rest (cdr sequence)))
           (display elem)))))
(define (filter sequence)
  (cond ((null? sequence) nil)
        (else
         (let ((elem (car sequence))
               (rest (cdr sequence)))
           (if (null? elem)
               (filter rest)
               (cons elem (filter rest)))))))
(define (filter sequence)
  (cond ((null? sequence) nil)
        ((null (car sequence)) (filter (cdr sequence)))
        (else (cons (car sequence) (filter (cdr sequence))))))
(define (filter sequence)
  (match sequence
    ['() '()]
    [(cons '() tail)
     (filter tail)]
    [(cons head tail)
     (cons head (filter tail))]))