Scheme - 定义定义

时间:2014-04-15 16:48:04

标签: scheme racket

过去两天我一直对完成这类问题感到困惑。

生成的函数(通过makeMixer)将整数N作为输入,并输出原始列表中的第N个项目。例如,如果makeListPickerFor按如下方式调用:

    (makeListPickerFor '(4 0 -2 -3 5))

将生成一个函数,该函数将整数作为输入,例如3, 并返回列表中的该项(对于3,它将输出-2,因为-2 是原始列表中的第3项。)

因此,如果原始呼叫如下:

   (define S (makeListPickerFor '(4 0 -2 -3 5)))

然后生成的函数S表现如下:

   (S 4)   *** would return -3, because -3 is the 4th item in the original list
   (S 2)   *** would return 0, because 0 is the 2nd item in the original list

任何正确方向的帮助都会有很大帮助。

3 个答案:

答案 0 :(得分:1)

这种现象称为closure。闭包基本上是makeListPickerFor以函数形式返回的内部状态。将其分配给某个名称S会导致S成为您可以进行后续调用的函数。然后,此函数可以在返回它的第一个函数的范围内访问该内部状态。

答案 1 :(得分:0)

尝试

(define (makeListPickerFor l)
  (lambda (n)
    (list-ref l n)))

所以makeListPickerFor返回一个仍然可以通过闭包访问初始列表l的函数。然后

> (define S (makeListPickerFor '(4 0 -2 -3 5)))
> (S 4)
5
> (S 2)
-2

请注意,在Scheme列表中,索引为0索引,因此结果如此。如果要使用1索引,请更改为

(define (makeListPickerFor l)
  (lambda (n)
    (list-ref l (- n 1))))

> (define S (makeListPickerFor '(4 0 -2 -3 5)))
> (S 4)
-3
> (S 2)
0

该程序也可以表示为

(define makeListPickerFor
  (lambda (l)
    (lambda (n)
      (list-ref l (- n 1)))))

这与前一个过程完全相同,因为(define (f x))(define f (lambda (x)))的语法糖,但更清楚它是一个返回过程的过程。

答案 2 :(得分:0)

以下是另一种定义它的方法:

(define (make-picker lst)
  (define (picker n)
    (list-ref lst (- n 1)))
  picker)

(define list-len 10000000)
(define f (make-picker (range list-len 0 -1)) ; range is #!racket specific
(f 1)        ; ==> 10000000
(f list-len) ; ==> 1

对于#!racket:

中非常大的列表,这是一个更有效的方法
(define (make-picker-hash lst)
  (define hash 
    (make-immutable-hasheqv (map cons 
                                 (range 1 (add1 (length lst))) 
                                 lst)))
  (lambda (x)
    (hash-ref hash x))) 

(define fh (make-picker-hash (range list-len 0 -1)))
(fh list-len) ; ==> 1
(fh 1)        ; ==> 10000000 (list-len)