SCHEME 可变函数

SCHEME Mutable Functions

在过去的几个月里,我一直在自学 Scheme R5RS,并且刚刚开始学习可变函数。我已经完成了几个这样的功能,但似乎发现了我对这个的错误。

(define (lst-functions)
  (let ((lst '()))
    (define (sum lst)     
      (cond ((null? lst) 0)
            (else
             (+ (car lst) (sum (cdr lst))))))
    (define (length? lst)
      (cond ((null? lst) 0)
            (else
             (+ 1 (length? (cdr lst))))))
    (define (average)
      (/ (sum lst) (length? lst)))
    (define (insert x)
      (set! lst (cons x lst)))
    (lambda (function)
      (cond ((eq? function 'sum) sum)
            ((eq? function 'length) length?)
            ((eq? function 'average) average)
            ((eq? function 'insert) insert)
            (else
             'undefined)))))

(define func (lst-functions))
((func 'insert) 2)
((func 'average))

你的一些函数是递归的,但定义时没有参数。因此 (sum (cdr lst)) 不应该工作,因为 sum 使用 lst。你可以通过定义一个助手来做到这一点:

(define (sum-rec lst)
  (if (null? lst)
      0
      (+ (car lst) (sum-rec (cdr lst)))))

或者使用累加器:

(define (sum-iter lst acc)
  (if (null? lst)
      acc
      (sum-iter (cdr lst) (+ (car lst) acc)))

您的 sum 当然会通过 lst:

使用它
(define (sum)
  (sum-iter lst 0))

或者您可以让驱动程序像这样部分应用它们:

(lambda (function)
      (cond ((eq? function 'sum) (lambda () (sum-iter lst))
            ...))

旁注。 length? 是一个奇怪的命名函数。名称末尾的问号通常保留给 return 真值或假值的函数,这显然是 return 一个数字。

您没有在使用它的过程中声明 lst 参数,而是在调用它们时传递了它。我标记了修改的行,试试这个:

(define (lst-functions)
  (let ((lst '()))
    (define (sum lst)     ; modified
      (cond ((null? lst) 0)
            (else
             (+ (car lst) (sum (cdr lst))))))
    (define (length? lst) ; modified
      (cond ((null? lst) 0)
            (else
             (+ 1 (length? (cdr lst))))))
    (define (average)
      (/ (sum lst) (length? lst)))
    (define (insert x)
      (set! lst (cons x lst)))
    (lambda (function)
      (cond ((eq? function 'sum) (lambda () (sum lst)))        ; modified
            ((eq? function 'length) (lambda () (length? lst))) ; modified
            ((eq? function 'average) average)
            ((eq? function 'insert) insert)
            (else
             'undefined)))))

现在它按预期工作了:

(define func (lst-functions))
((func 'insert) 2)

((func 'average)) 
=> 2
((func 'sum))
=> 2
((func 'length))
=> 1