2013-08-29 30 views
5

Devam, bir sonraki değerde ne olacağını açıklıyor, değil mi? Bu sadece bir değer alan ve bazı hesaplamalar yapan bir işlev değil midir? Bir devamı bir işlevden ayıran nedir?

(+ (* 2 3) 5) 

(* 2 3) devamı burada call/cc kullanarak ve işlevini k kullanmayan anlamı nedir (+ _ 5)

(define k (lambda (v) (+ v 5))) 

nedir?

+0

Geçerli devamı olan (işlev olarak) argümanı * olan * çağrı/cc' kullanamazsınız. 'Call/cc' kullanmak için sorunuzu düzenleyin! Devam oku [devam] (http://en.wikipedia.org/wiki/Continuation) –

+0

Arama/cc'yi kullanmıyorum, eşdeğer bir fonksiyon kullanıyorum sürekliliği temsil ediyor mu? – ayhid

+0

Devam sözdizimsel olarak bir işlevdir, ancak bir kontrol aktarımını temsil eder. Çağrı protokolü bir fonksiyondan farklıdır - asla geri dönmemesi gerekiyordu. –

cevap

6

Doğru. Tüm programlar duruncaya kadar devam eder. Bir devamı, temelde uygulama tarafından yapılan hesaplamada genellikle bir adımdır.

Sizin örnek: * İlk bitirmek için

(+ (* 2 3) 5) 

kombinasyonu + kombinasyonu bağlıdır. Böylece (+ result 5), (* 2 3)'un devamıdır. Bu bağlamda bir prosedür değil. call/cc'un faydası, bir devamlılığınız olduğunda pişmanlık duyuyorsunuz ve bunun yerine başka bir şey yapmak istiyor ya da daha sonra tekrar gelmek istiyorsanız. İlk yapmak Sağlar:

(define g 0) 
(call/cc 
    (lambda (exit) 
    (/ 10 (if (= g 0) (exit +Inf.0) g)))) 

Açıkçası, devamı olan bir bölümü olduğunda sonucu yapılır, ancak exit beri kısa + Inf.0 dönmek için devre alır şeyi çalıştırılırsa.

Bunu daha sonra bölümlemeyi yapmadan bir prosedürle nasıl yaparsınız? Bu tarzda, yapamazsın.

Şema, kodunuzu Continuation Passing Style(=CPS) koduna dönüştürdüğünden ve CPS çağrısı/cc'de özel olmadığından bu gerçekten sihir değildir. CPS'de önemsiz yazma kodu değil.

İşte call/cc

(define (kcall/cc k consumer) 
    (consumer k (lambda (ignore v) (k v)))) 
4

Tebrikler CPS tanımı var! Devam eden geçiş tarzını icat ettiniz! Yaptığınız ve call/cc arasındaki tek fark, call/cc'un otomatik olarak yapması ve kodunuzu yeniden yapılandırmanızı gerektirmemesidir.

2

Bir 'devam', bir hesaplamanın tüm geleceğidir. Bir hesaplamadaki her nokta, mevcut durumda, mevcut program-sayaç ve mevcut yığın olarak düşünebileceğiniz bir devamlılığa sahiptir. Şema call/cc fonksiyonu, mevcut konfigürasyonu rahatça yakalar ve bir fonksiyona dönüştürür. Bu işlevi çağırdığınızda, hesaplamada bu noktaya geri dönersiniz. Böylece, bir devam etme, bir fonksiyondan çok farklıdır (ancak devam fonksiyonu, iyi bir işlevdir).

  1. yerel olmayan çıkış:

    uygulanan bir tipik call/cc görür iki yaygın durumlar vardır. Sürekliliği başlattığınız hesaplamayı aniden sona erdirmek için bir hesaplama yaparsınız, bir hesaplama yaparsınız. Bir hesaplamayı yeniden başlat/yeniden girme

  2. . Bu durumda devamınızı kaydedin ve istediğiniz gibi tekrar arayın.İşte

vaka # 1 için bir örnek:

(begin 
    ;; do stuff 
    (call/cc (lambda (k) 
       ;; do more 

      ;; oops, must 'abort' 
      (k 'ignore))) 
    ;; continue on 
) 

Ve burada bir vaka # 2 için örnektir: Bu durumda 2. For

> (define C#f) 
> (let ((x 10)) 
    (display (list (+ 1 (call/cc (lambda (k) (set! c k) x))) 111)) 
    (display " more")) 
(11 111) more 
> (c 20) 
(21 111) more 
> (c 90) 
(91 111) more 

o dikkati çekiyor devamı, size en üst düzey okuma-değerlendirme-baskı döngüsüne geri dönmenizi sağlar - bu, bu örnekte sürekliliği yeniden ortaya koyma şansı verir!