2009-04-03 52 views
120

Sự khác biệt giữa coroutine và sự tiếp tục và máy phát điện là gì?Coroutine vs Continuation vs Generator

+1

Tôi tự hỏi liệu coroutines và continuations có hiệu quả tương đương hay không. Tôi biết có thể mô hình hóa các coroutine với sự tiếp tục, nhưng liệu có thể mô hình hóa sự tiếp nối với coroutin hay không bởi vì sự tiếp tục nghiêm ngặt hơn? – nalply

Trả lời

102

Tôi sẽ bắt đầu với máy phát điện, vì đây là trường hợp đơn giản nhất. Như @zvolkov đã đề cập, chúng là các hàm/đối tượng có thể liên tục được gọi mà không trả về, nhưng khi được gọi sẽ trả về (lợi nhuận) một giá trị và sau đó tạm ngưng thực thi. Khi họ được gọi một lần nữa, họ sẽ bắt đầu từ nơi họ cuối cùng bị đình chỉ thực hiện và làm điều của họ một lần nữa.

Một máy phát cơ bản là một cắt giảm (không đối xứng) coroutine. Sự khác biệt giữa một coroutine và máy phát điện là một coroutine có thể chấp nhận các đối số sau khi nó được gọi ban đầu, trong khi một máy phát điện thì không.

Hơi khó với một số ví dụ nhỏ về nơi bạn sử dụng coroutines, nhưng đây là thử nghiệm tốt nhất của tôi. Lấy mã Python (tạo thành) này làm ví dụ.

def my_coroutine_body(*args): 
    while True: 
     # Do some funky stuff 
     *args = yield value_im_returning 
     # Do some more funky stuff 

my_coro = make_coroutine(my_coroutine_body) 

x = 0 
while True: 
    # The coroutine does some funky stuff to x, and returns a new value. 
    x = my_coro(x) 
    print x 

Một ví dụ về nơi coroutines được sử dụng là lexers và phân tích cú pháp. Nếu không có coroutines trong ngôn ngữ hoặc giả lập bằng cách nào đó, lexing và phân tích mã cần phải được trộn lẫn với nhau mặc dù họ đang thực sự hai mối quan tâm riêng biệt. Nhưng bằng cách sử dụng một coroutine, bạn có thể tách ra mã lexing và phân tích cú pháp.

(Tôi sẽ đánh dấu sự khác biệt giữa các đối xứng và không đối xứng coroutines. Có thể nói rằng chúng tương đương nhau, bạn có thể chuyển đổi từ cái này sang cái khác, và các coroutines bất đối xứng - giống như máy phát điện - Dễ hiểu hơn. Tôi đã phác họa cách người ta có thể thực hiện các coroutines bất đối xứng trong Python.)

Tiếp tục là những con thú thực sự khá đơn giản. Tất cả chúng là các hàm đại diện cho một điểm khác trong chương trình, nếu bạn gọi nó, sẽ làm cho việc thực hiện tự động chuyển sang điểm mà hàm đại diện. Bạn sử dụng phiên bản rất hạn chế của chúng mỗi ngày mà không hề nhận ra. Ví dụ, ngoại lệ, có thể được coi là một loại tiếp tục từ trong ra ngoài. Tôi sẽ cung cấp cho bạn một ví dụ giả mã dựa trên Python về sự tiếp tục.

Giả sử Python có hàm gọi là callcc() và hàm này lấy hai đối số, hàm đầu tiên là hàm và thứ hai là danh sách đối số để gọi hàm. Hạn chế duy nhất đối với chức năng đó sẽ là đối số cuối cùng cần có sẽ là một hàm (đó sẽ là sự tiếp tục hiện tại của chúng ta).

def foo(x, y, cc): 
    cc(max(x, y)) 

biggest = callcc(foo, [23, 42]) 
print biggest 

Điều gì sẽ xảy ra là callcc() sẽ lần lượt gọi foo() với việc tiếp tục hiện tại (cc), có nghĩa là, một tham chiếu đến các điểm trong chương trình mà tại đó callcc() được gọi. Khi foo() gọi sự tiếp tục hiện tại, về cơ bản giống như yêu cầu callcc() trả lại bằng giá trị bạn đang gọi là tiếp tục hiện tại, và khi thực hiện điều đó, nó sẽ quay trở lại vị trí tiếp tục hiện tại, tức là khi bạn gọi là callcc().

Kết quả của tất cả điều này sẽ là biến thể Python giả định của chúng tôi sẽ in '42'.

Tôi hy vọng điều đó sẽ hữu ích và tôi chắc chắn rằng lời giải thích của tôi có thể được cải thiện một chút!

+6

Một nit: _delimited_ continuations là các hàm, nhưng _undelimited_ continuations không phải là: http://okmij.org/ftp/continuations/undelimited.html#delim-vs-undelim –

+2

Đó là một điểm tốt. Điều đó nói rằng, trong hầu hết các ứng dụng thực tế, khi mọi người nói 'tiếp tục', họ đang nói về việc tiếp tục một phần/giới hạn. Đưa vào các loại khác nhau của tiếp tục sẽ lúng túng lời giải thích lên một chút. –

+1

Continuations không hoạt động, mặc dù chúng có thể được chỉnh sửa lại thành các hàm. "Điều đó nói rằng, trong hầu hết các ứng dụng thực tế, khi mọi người nói 'tiếp tục', họ đang nói về sự tiếp tục một phần/giới hạn." Bạn có chỉ ra cách sử dụng thuật ngữ "tiếp tục" này không? Tôi chưa bao giờ gặp việc đó. Ngoài ra, bạn đã đưa ra một ví dụ cho một sự tiếp tục không bị giới hạn, bằng cách sử dụng cuộc gọi/cc. Các toán tử để tiếp tục phân tách thường là "reset" và "shift" (chúng có thể có các tên khác). – Ivancho

28

Coroutine là một trong nhiều thủ tục thay phiên nhau thực hiện công việc của họ và sau đó tạm dừng để kiểm soát các coroutines khác trong nhóm.

Tiếp tục là "con trỏ đến hàm", bạn chuyển sang một số quy trình, được thực hiện ("tiếp tục với") khi thực hiện quy trình đó.

Máy phát điện (in .NET) là một cấu trúc ngôn ngữ có thể nhổ ra một giá trị, "tạm dừng" thực hiện phương thức và sau đó tiến hành từ cùng một điểm khi được hỏi giá trị tiếp theo.

+0

Tôi nhận ra câu trả lời có thể không chính xác nhưng ở cấp độ câu hỏi này tôi đã cố gắng giữ cho nó đơn giản. Bên cạnh đó, tôi không thực sự hiểu hết điều này :) – zvolkov

+0

Một máy phát trong python tương tự như phiên bản C#, nhưng được thực hiện như một cú pháp đặc biệt để tạo một thể hiện của đối tượng iterator, trả về các giá trị được trả về bởi hàm "định nghĩa bạn cung cấp. – Benson

+2

Một sửa đổi nhỏ: "... bao gồm cả ngăn xếp cuộc gọi và tất cả các biến NHƯNG KHÔNG GIÁ TRỊ CỦA CHÚNG TÔI" (hoặc chỉ cần thả "tất cả các biến"). Continuations không bảo tồn các giá trị, chúng chỉ chứa stack call. – nalply

7

Trong phiên bản mới hơn của Python, bạn có thể gửi giá trị cho Máy phát điện với generator.send(), làm cho máy phát điện python có hiệu quả coroutines.

Sự khác biệt chính giữa Máy phát điện trăn và máy phát điện khác, nói là greenlet, là trong python, yield value của bạn chỉ có thể trả lại người gọi. Trong khi trong greenlet, target.switch(value) có thể đưa bạn đến một coroutine đích cụ thể và mang lại một giá trị trong đó target sẽ tiếp tục chạy.

+3

Nhưng trong Python, tất cả các lệnh gọi 'yield' phải nằm trong cùng một hàm, được gọi là" Generator ". Bạn không thể 'yield' từ một hàm con, đó là lý do tại sao Python được gọi là * semi-coroutines *, trong khi Lua có * coroutines bất đối xứng *. (Có đề xuất để tuyên truyền sản lượng, nhưng tôi nghĩ rằng những người chỉ bùn nước.) – cdunn2001

+4

@ cdunn2001: (bình luận của Winston) Python3.3 giới thiệu biểu thức "năng suất từ" cho phép bạn thu được từ máy phát điện phụ. –

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