2015-12-15 62 views
1

我用的球拍,我得到的結果爲4以下簡單的代碼:執行下面的呼叫/ cc的EXP

(let/cc done 
    ((let/cc esc 
    (done (+ 1 (let/cc k 
        (esc k))))) 
    3)) 

和我要執行這個代碼一步一步的。

首先,我改變了第一let/cccall/cc形式象下面這樣:

(call/cc (λ (done) 
      ((let/cc esc 
       (done (+ 1 (let/cc k 
          (esc k))))) 
      3))) 

當然,這產生4也。

其次,因爲我發現call/cc機制在internet它說call/cc做以下4個步驟:

  1. 捕獲當前的延續。
  2. 構造一個函數C,它接受一個參數,並將該當前延續與該參數值一起應用。
  3. 將此函數作爲參數傳遞給expr ---即調用(expr C)
  4. 返回評估結果(expr C),除非expr調用C,在這種情況下返回傳遞給C的值。

因此,我已按照上述針對第一call/cc等步驟:

  1. 電流繼續是一個身份。
  2. C指的是(λ (x) x)
  3. 由於expr(λ (done) ((let/cc esc (done (+ 1 (let/cc k (esc k))))) 3))是,(expr C)是:

((λ (done) 
    ((let/cc esc 
     (done (+ 1 (let/cc k 
        (esc k))))) 
    3)) 
(λ (x) x)) 
  • 要返回的上面的代碼的結果值,在我球拍以上執行。
  • 但是,上面的代碼(由我修改)不執行,併產生一個錯誤:

    application: not a procedure;

    expected a procedure that can be applied to arguments

    given: 4

    arguments...:

    3

    請我做錯了什麼。我混淆了延續的概念。謝謝。

    回答

    0

    繼續不只是關閉(功能)。他們還執行跳轉到他們在代碼中的定義位置。您必須完全執行CPS轉換才能嘗試評估Scheme解釋器中生成的表達式。該表達式將只包含lambda和沒有延續(在意義上的call/cc(1))。

    您嘗試的表達式將它們混合在一起 - 它將done定義爲簡單的lambda-定義的函數,但它仍作爲延續使用於嵌套上下文中。


    (1)混亂的另一個來源是在調用繼續傳遞風格「延續」函數的參數。他們是不是;它們在這個或那個可能性中是「被稱爲」的簡單函數,因此它們也被稱爲「延續」。請參閱another example of call/cc code translation

    按照這種方法,你的翻譯方案的代碼到Common Lisp的,我們得到:

    ;; (let/cc done 
    ;; ((let/cc esc 
    ;;  (done (+ 1 (let/cc k 
    ;;     (esc k))))) 
    ;; 3)) 
    (prog (retval done arg1 func esc arg2 k arg3 arg4) 
        (setq done (lambda(x) (setq retval x) (go DONE)))  ; 3 
        (setq arg1 3)          ; 5 
         (setq esc (lambda(x) (setq func x) (go ESC)))  ; 8 
         (setq arg3 1)          ; 10 
         (setq k (lambda(x) (setq arg4 x) (go K)))  ; 12 
         (setq arg4 (funcall esc k))      ; 13 
        K              ; 11 
         (setq arg2 (+ arg3 arg4))       ; 9 
         (setq func (funcall done arg2))      ; 7 
        ESC              ; 6 
        (setq retval (funcall func arg1))     ; 4 
        DONE             ; 2 
        (return retval))          ; 1 
    

    這的確returns 4(代碼行是爲了在翻譯過程中編號爲它們被寫入)。

    1

    當口譯人員看到call/cc時,即使不做CPS的口譯員也會對該子樹執行此操作。你的代碼看起來像這樣:

    ((λ (done) 
        ((λ (esc)  
         ((λ (k) (esc k)) 
         (λ (r) (k+ done 1 r)))) 
        (λ (v) (v 3)))) 
    values) 
    
    
    ; k+ implementation (+, but CPS) 
    (define (k+ k . args) 
        (k (apply + args)))