2013-08-29 23 views
5

Tiếp tục mô tả điều gì xảy ra tiếp theo với một số giá trị, đúng không? Đó không chỉ là một hàm có giá trị và thực hiện một số tính toán?Điều gì phân biệt sự tiếp tục của một hàm?

(+ (* 2 3) 5) 

việc tiếp tục (* 2 3)(+ _ 5)

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

điểm của việc sử dụng call/cc ở đây và không sử dụng các chức năng k là gì?

+0

Bạn không sử dụng 'call/cc' mà đối số * là * lấy phần tiếp theo hiện tại (dưới dạng hàm). Chỉnh sửa câu hỏi của bạn để sử dụng 'call/cc'! Đọc wikipage trên [tiếp tục] (http://en.wikipedia.org/wiki/Continuation) –

+0

Tôi không sử dụng cuộc gọi/cc, tôi đang sử dụng một hàm tương đương đại diện cho việc tiếp tục? – ayhid

+0

Tiếp tục là cú pháp một hàm nhưng nó đại diện cho một chuyển điều khiển. Giao thức cuộc gọi của nó khác với chức năng của nó - nó không bao giờ được trả về. –

Trả lời

6

True. Tất cả các chương trình đều tiếp tục cho đến khi nó dừng lại. Một tiếp tục thường là một bước trong phép tính được thực hiện bởi việc triển khai cơ bản.

dụ của bạn:

(+ (* 2 3) 5) 

Sự kết hợp + là phụ thuộc vào sự kết hợp * để kết thúc đầu tiên. Do đó, (+ result 5) thực sự là sự tiếp tục của (* 2 3). Nó không phải là một thủ tục trong bối cảnh này mặc dù. Tính hữu dụng của call/cc là khi bạn có một sự tiếp tục bạn hối tiếc và muốn làm điều gì đó khác thay vào đó hoặc bạn muốn quay lại điều này sau đó. Cho phép thực hiện đầu tiên:

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

Rõ ràng, có một bộ phận mà là sự tiếp nối khi kết quả của sự nếu được thực hiện, nhưng vì exit được điều hành toàn bộ điều bị ngắn mạch trở về + Inf.0.

Bạn sẽ làm điều đó như thế nào với quy trình mà không cần phải thực hiện việc phân chia sau đó? Theo phong cách này, bạn không thể.

Nó không thực sự kỳ diệu vì Đề án chuyển đổi mã của bạn thành Continuation Passing Style(=CPS) và trong CPS call/cc không có gì đặc biệt. Nó không phải là viết mã tầm thường trong CPS.

Đây là định nghĩa CPS của call/cc

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

Xin chúc mừng! Bạn vừa phát minh ra phong cách tiếp tục đi qua! Sự khác biệt duy nhất giữa những gì bạn đã thực hiện và call/cc là tự động thực hiện call/cc và không yêu cầu bạn phải cấu trúc lại mã của mình.

2

'Tiếp tục' là toàn bộ tương lai của tính toán. Mỗi điểm trong một tính toán có một sự tiếp tục mà, trong điều kiện ngây thơ, bạn có thể nghĩ đến như là ngăn xếp chương trình hiện tại và ngăn xếp hiện tại. Chức năng Đề án call/cc thuận tiện nắm bắt cấu hình hiện tại và đóng gói nó thành một hàm. Khi bạn gọi hàm đó, bạn quay trở lại điểm đó trong tính toán. Do đó, một sự tiếp nối rất khác với một hàm (nhưng hàm tiếp tục là, một hàm).

Có hai trường hợp phổ biến nơi người ta thường thấy call/cc áp dụng:

  1. thoát phi địa phương. Bạn thiết lập một sự tiếp tục, làm một số tính toán, để đột ngột kết thúc tính toán bạn gọi sự tiếp tục.

  2. khởi động lại/nhập lại một tính toán. Trong trường hợp này, bạn lưu tiếp tục và sau đó gọi lại lần nữa như bạn muốn.

Dưới đây là một ví dụ cho trường hợp # 1:

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

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

Và đây là một ví dụ cho trường hợp # 2:

> (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 

Đối với trường hợp này # 2 là nó đáng chú ý là việc tiếp tục đưa bạn trở lại vòng lặp đọc-in-cấp cao nhất - cung cấp cho bạn một cơ hội để gọi lại sự tiếp tục trong ví dụ này!

Các vấn đề liên quan