如何使用 Scheme 编写计算整数列表的最大值和最小值的函数

How to write a function that computes the maximum and minimum of a list of integers using Scheme

我是 scheme 新手。我正在尝试使用方案查找列表的最大值和最小值。使用 "loop" 我能够得到答案。现在我正在尝试不同的方式来实现同样的事情。我做了一些更改,但出于某种原因我找不到我做错了什么。

    ;non working version  
    (define (min-max list1)
    (let (ls list1) (max (car list1)) (min(car list1))
      (cond 
         ((null? ls) 
                (list "max: " max "min: " min))
         ((> (car ls) max) 
             (let ((car ls) max))
             (min-max (cdr ls))) 
         ((< (car ls) min) 
             (let ((car ls) min))
              (min-max (cdr ls)))
        (else
              (min-max (cdr ls))))))
    (define list1(list 1 2 3 4 ))
    (display list1)
    (newline)
    (min-max list1)

    ;working version
    (define (min list1)
       (let loop((ls list1) (max (car list1)) (min(car list1)))
        (cond 
         ((null? ls) 
                (list "max: " max "min: " min))
          ((> (car ls) max) 
             (loop (cdr ls)(car ls) min))
         ((< (car ls) min) 
             (loop (cdr ls) max (car ls) ))
        (else 
              (loop (cdr ls) max min)))))

        (define list1(list 1 2 3 4 ))

        (display list1)
        (newline)
        (min list1)

这不是代码审查,但我将首先从您的程序的 "working" 版本开始。就目前而言,该过程不适用于空列表,因此您应该为此添加一个测试。然后,无需将列表的第一个元素重新与 minmax 进行比较。然后,你好像认为loop是关键字,所以我把名字改成了helper。最后,我修改了它以减少重复:

(define (min-max lst)
  (if (null? lst)
      '()
      (let helper ((lst (cdr lst)) (min (car lst)) (max (car lst)))
        (if (null? lst)
            (list min max)
            (let ((c (car lst)))
              (helper (cdr lst)
                      (if (< c min) c min)
                      (if (> c max) c max)))))))

相同
(define (min-max lst)
  (define (helper lst min max)
    (if (null? lst)
        (list min max)
        (let ((c (car lst)))
          (helper (cdr lst)
                  (if (< c min) c min)
                  (if (> c max) c max)))))
  (if (null? lst)
      '()
      (helper (cdr lst) (car lst) (car lst))))

测试:

> (min-max '(1 2 3 4))
'(1 4)
> (min-max '(1 8 2 3 4))
'(1 8)
> (min-max '())
'()

您的第一个过程不起作用,因为在每次递归调用时您都重新初始化 minmax。此外,由于没有对空列表进行测试,因此不可避免地最终会使用空列表的 car,这在 Scheme 中是不允许的。最后,看起来你想在递归调用之外更改 minmax 的值,这意味着你必须使用 set!。这是它的一个工作版本:

(define (min-max lst)
  (if (null? lst)
      '()
      (let ((min (car lst)) (max (car lst)))
        (define (helper lst)
          (if (null? lst)
              (list min max)
              (let ((c (car lst)))
                (when (< c min) (set! min c))
                (when (> c max) (set! max c))
                (helper (cdr lst)))))
        (helper lst))))

这会产生相同的结果,但您可以看到与 helper.

的递归调用相比,使用 set! 的代码看起来有多么不优雅