如何在不删除方案中的元素的情况下遍历列表中的每个元素

How to iterate through every element in list without removing elements in scheme

我的问题是使用 Racket R5RS 语言制作一个简单的加减程序。题目的基本思路是在list中的每个元素前都加上plus/minus符号,判断结果是否是list中的元素之一。以下是我现在拥有的:

(define plus-minus (lambda (lst l sum)
                (cond
                  ((null? lst)
                   (cond
                     ((null? l) #f)
                     ((= sum (car l)) #t)
                     (else (plus-minus lst (cdr l) sum))))
                  ((plus-minus (cdr lst) l (+ sum (car lst))) #t)
                  ((plus-minus (cdr lst) l (- sum (car lst))) #t)
                  (else #f))))

这段代码可以,但是要求参数中只能有一个列表,其他都是数字。第一次调用该函数时,我的代码中的前两个参数是相同的。第一个是获得总和的那个。第二个是检查总和是否等于列表中的元素之一。这两个列表都是必需的,因为当我得到总和时,第一个列表中的元素被删除。
我的问题是,如何去掉参数中的第二个列表?无论如何我可以在不删除元素的情况下遍历列表(CDR 推荐)?

首先是你的代码部分

(cond
  ((null? l) #f)
  ((= sum (car l)) #t)
  (else (plus-minus lst (cdr l) sum))))

是检查sum是否在l中。有一个函数可以做到这一点,它已经被称为 member,所以你可以用 (member sum l) 替换整个块,这样更干净。

我也想先纠正一个错误的认识。 cdr 不会 从列表中删除元素。列表被定义为一个空列表,或者一对元素和另一个列表。例如

[1 [2 [3 empty]]]

是一个包含三个元素的列表:123car 所做的是获取该对的第一个元素。 cdr 所做的是获取该对的第二个元素。没有删除任何内容。

要去掉额外的参数,您可能需要将此函数重命名为另一个函数,例如 plus-minus-helper,并创建 plus-minus,然后调用 plus-minus-helperplus-minus 则为:

(define (plus-minus lst)
  (plus-minus-helper lst lst 0))

或者,如果你想在一个函数中完成所有事情,你也可以使用 letrecplus-minus 中绑定 plus-minus-helper,或者使用 let 的形式letrec。通过这些方式,您还可以引用输入的原始参数,因此您不需要另一个参数。

(define (plus-minus init-lst)
  (let plus-minus-helper ((lst init-lst)
                          (sum 0))
    (cond
      ((null? lst) (member sum init-lst))
      ((plus-minus-helper (cdr lst) (+ sum (car lst))) #t)
      ((plus-minus-helper (cdr lst) (- sum (car lst))) #t)
      (else #f))))