Apa perbedaan antara coroutine dan lanjutan dan generator?
Apa perbedaan antara coroutine dan lanjutan dan generator?
Jawaban:
Saya akan mulai dengan generator, karena mereka adalah kasus paling sederhana. Seperti @zvolkov sebutkan, mereka adalah fungsi / objek yang dapat berulang kali dipanggil tanpa kembali, tetapi ketika dipanggil akan mengembalikan (menghasilkan) nilai dan kemudian menunda eksekusi mereka. Ketika mereka dipanggil lagi, mereka akan mulai dari tempat mereka menunda eksekusi dan melakukan hal mereka lagi.
Generator pada dasarnya adalah coroutine yang dipotong (asimetris). Perbedaan antara coroutine dan generator adalah coroutine dapat menerima argumen setelah awalnya disebut, sedangkan generator tidak bisa.
Agak sulit untuk memberikan contoh sepele tentang di mana Anda akan menggunakan coroutine, tetapi inilah upaya terbaik saya. Ambil ini (dibuat) kode Python sebagai contoh.
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
Contoh di mana coroutine digunakan adalah lexers dan parser. Tanpa coroutine dalam bahasa atau ditiru bagaimanapun, kode lexing dan parsing perlu dicampur bersama meskipun mereka benar-benar dua masalah yang terpisah. Tetapi menggunakan coroutine, Anda dapat memisahkan kode lexing dan parsing.
(Saya akan membahas perbedaan antara coroutine simetris dan asimetrik. Cukup dengan mengatakan bahwa mereka setara, Anda dapat mengkonversi dari satu ke yang lain, dan coroutine asimetris - yang merupakan generator yang paling mirip - adalah lebih mudah untuk dipahami. Saya menjelaskan bagaimana seseorang dapat menerapkan coroutine asimetris dengan Python.)
Kelanjutan sebenarnya adalah binatang yang sangat sederhana. Semua itu adalah fungsi yang mewakili titik lain dalam program yang, jika Anda menyebutnya, akan menyebabkan eksekusi secara otomatis beralih ke titik yang diwakili fungsi tersebut. Anda menggunakan versi yang sangat terbatas setiap hari tanpa menyadarinya. Pengecualian, misalnya, dapat dianggap sebagai semacam kelanjutan dari dalam ke luar. Saya akan memberi Anda contoh pseudocode berbasis Python dari kelanjutan.
Katakanlah Python memiliki fungsi yang disebut callcc()
, dan fungsi ini mengambil dua argumen, yang pertama adalah fungsi, dan yang kedua adalah daftar argumen untuk memanggilnya. Satu-satunya batasan pada fungsi itu adalah bahwa argumen terakhir yang diambil adalah fungsi (yang akan menjadi kelanjutan kami saat ini).
def foo(x, y, cc):
cc(max(x, y))
biggest = callcc(foo, [23, 42])
print biggest
Apa yang akan terjadi adalah yang callcc()
pada gilirannya akan memanggil foo()
dengan kelanjutan saat ini ( cc
), yaitu, referensi ke titik dalam program di mana callcc()
dipanggil. Ketika foo()
memanggil kelanjutan saat ini, itu pada dasarnya sama dengan mengatakan callcc()
untuk kembali dengan nilai yang Anda panggil kelanjutan saat ini, dan ketika melakukan itu, itu memutar kembali tumpukan ke tempat kelanjutan saat ini dibuat, yaitu, ketika Anda menelepon callcc()
.
Hasil dari semua ini adalah bahwa varian Python hipotetis kita akan dicetak '42'
.
Saya harap itu membantu, dan saya yakin penjelasan saya dapat ditingkatkan sedikit!
Coroutine adalah salah satu dari beberapa prosedur yang bergantian melakukan pekerjaan mereka dan kemudian berhenti untuk memberikan kontrol kepada coroutine lain dalam kelompok.
Lanjutan adalah "penunjuk ke fungsi" yang Anda lewati untuk beberapa prosedur, yang akan dieksekusi ("dilanjutkan dengan") ketika prosedur itu dilakukan.
Generator (dalam. NET) adalah konstruksi bahasa yang dapat memuntahkan nilai, "menjeda" pelaksanaan metode dan kemudian melanjutkan dari titik yang sama ketika ditanya untuk nilai berikutnya.
Dalam versi Python yang lebih baru, Anda dapat mengirim nilai ke Generator dengan generator.send()
, yang membuat Generator python secara efektif coroutine.
Perbedaan utama antara Generator python, dan generator lainnya, katakanlah greenlet, adalah bahwa dengan python, Anda yield value
hanya dapat kembali ke pemanggil. Sementara di greenlet, target.switch(value)
dapat membawa Anda ke target coroutine tertentu dan menghasilkan nilai di mana target
akan terus berjalan.
yield
panggilan harus dalam fungsi yang sama, yang disebut "Generator". Anda tidak dapat yield
dari sub-fungsi, itulah sebabnya Python disebut semi-coroutine , sedangkan Lua memiliki coroutine asimetris . (Ada proposal untuk memperbanyak hasil panen, tetapi saya pikir itu hanya membuat lumpur air.)