簡體   English   中英

收集器函數在 Scheme 中是如何工作的?

[英]How do collector functions work in Scheme?

我無法理解 Scheme 中收集器函數的使用。 我正在使用“The Little Schemer”一書(由 Daniel P. Friedman 和 Matthias Felleisen 撰寫)。 一個帶有一些解釋的綜合示例將極大地幫助我。 以下代碼段是使用收集器函數的函數示例:

(define identity
  (lambda (l col)
    (cond
      ((null? l) (col '()))
      (else (identity
              (cdr l)
              (lambda (newl)
                (col (cons (car l) newl))))))))

...以示例調用為(identity '(abc) self)self-function(define self (lambda (x) x)) identity函數返回給定的列表l ,因此給定調用的輸出將是(abc) 使用的確切語言是 R5RS Legacy 語言。

鑒於identity定義中如何定義這些“收集器”函數,調用

(identity xs col)

對於任何列表xs和一些“收集器”函數col ,相當於調用

(col xs)

所以相同的列表將被“返回”,即傳遞給它的參數“收集器”/繼續函數col 這就解釋了它的名字, identity ,然后。

為了比較, reverse可以編碼為

(define reverse     ; to be called as e.g. (reverse l display)
  (lambda (l col)
    (cond
      ((null? l) (col '()))        ; a reversed empty list is empty
      (else (reverse (cdr l)       ; a reversed (cdr l) is newl --
                     (lambda (newl)    ; what shall I do with it when it's ready?
                       (col            ; append (car l) at its end and let col
                          (append newl                           ; deal with it!
                                  (list (car l))))))))))

這種編程風格被稱為continuation-passing 風格:每個函數都被傳遞一個“continuation”,假定它將傳遞其余計算的結果,因此原始的 continuation/collector 函數將傳遞最終結果最終。 每個收藏家的說法代表了未來的“結果”,它將接收和收集功能本身,然后指定它是如何被處理,然后

不要被術語混淆:這些函數不是call/cc函數捕獲的“延續”,它們是普通的 Scheme 函數,代表“接下來要做什么”。

定義可以理解為

identity :
  to transform a list xs 
        with a collector function col,
    is 
    | to call (col xs)                              , if xs is empty, or
    | to transform (cdr xs)  
        with a new collector function col2  
        such that
              (col2 r)  =  (col (cons (car xs) r))  , otherwise.

(或者我們可以用偽代碼編寫,如)

(identity list col)  =
  | empty? list           ->  (col list)
  | match? list (x . xs)  ->  (identity xs col2)
                                where 
                                (col2 r)  =  (col (cons x r))

col2通過將(cons xr)傳遞給前一個處理程序col來處理其參數r 這意味着r被轉換為(cons xr) ,但它不是作為值返回,而是被送入col進行進一步處理。 因此,我們通過將新值(cons xr)傳遞給前一個“收集器”來“返回”新值。

示例調用,作為說明:

(identity (list 1 2 3) display)     

= (identity (list 2 3) k1)
      ; k1 =  (lambda (r1) (display (cons 1 r1)))           =  display ° {cons 1}

= (identity (list 3)  k2)
      ; k2 =  (lambda (r2) (k1 (cons 2 r2)))                     =  k1 ° {cons 2} 

= (identity (list )  k3)
      ; k3 =  (lambda (r3) (k2 (cons 3 r3)))                     =  k2 ° {cons 3} 

= (k3 '())                        ; (((display ° {cons 1}) ° {cons 2}) ° {cons 3}) []

= (k2 (cons 3 '()))                    ; ((display ° {cons 1}) ° {cons 2}) [3]

= (k1 (cons 2 (list 3)))                    ; (display ° {cons 1}) [2,3]

= (display (cons 1 (list 2 3)))                  ; display [1,2,3]

= (display (list 1 2 3))

更新:在我最近喜歡使用的模式匹配偽代碼中,我們可以寫

identity []        col  =  col []
identity [a, ...d] col  =  identity d ( newl =>  col [a, ...newl] )

reverse  []        col  =  col []
reverse  [a, ...d] col  =  reverse  d ( newl =>  col [...newl, a] )

希望它在視覺上非常明顯,幾乎不需要解釋!

我正在添加第二個答案,希望它可以澄清剩余的疑問,以防您有任何疑問(因為缺少“已接受”標記表明)。

在 Gerald J. Sussman 的聲音中,正如在 SICP 講座中聽到/看到的那樣,視頻在互聯網管道上隨處可見,我們可以在寫作時閱讀它,

(define identity

“身份”被定義為

  (lambda

那個函數,當給定

           (l col)

兩個參數, lcol ,將

    (cond
      ((null? l)

-- 如果(null? l)為真 --

  • 好的,這意味着l是一個列表,注意

     (col '()))

返回表達式的值(col '())

  • 好的,現在這意味着col是一個函數,需要一個參數,作為一種可能是空列表,
      (else (identity (cdr l)

否則它將使用更新的值進行尾遞歸調用,一個是(cdr l)

                      (lambda (newl)
                        (col (cons (car l) newl)))))))

另一個是新構造的函數,這樣當被調用時,它的參數為newl (一個列表,正如對col預期——因為它出現在相同的角色中,它必須遵循相同的約定),將依次使用由前綴(car l)到列表newl產生的非空列表調用函數col

因此,這個函數, identity ,遵循方程

( identity   (cons (car l) (cdr l))           col                        )
==
( identity       (cdr l)     (lambda (newl)  (col  (cons (car l) newl))) )

( identity   '()   col )
==
( col        '()       )

描述一個迭代過程,這個過程將函數調用

(identity [a,      b,      c, ...,    n]    col      )

進入通話

(col
     (cons a (cons b (cons c ... (cons n '()) ... ))))

重新創建完全相同的列表,然后將其作為參數提供給已提供的函數col

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM