ジェネレーター対継続対コルーチン
-
23-08-2019 - |
質問
コルーチンと継続と発電機の違いは何ですか?
解決
私は、彼らが最も単純なケースだと見て、発電機から始めましょう。 @zvolkovが述べたように、彼らは繰り返し戻らずに呼び出すことができる関数/オブジェクトだが、呼び出されたときに値を(歩留まり)を返し、その後、その実行を一時停止します。彼らは再び呼び出されているとき、彼らは最後の一時停止実行から起動して、もう一度自分のことを行います。
ジェネレータは、本質的に削減(非対称)コルーチンです。コルーチンと発電機との違いは、発電ができないのに対し、それは最初に、呼ばれています後コルーチンは引数を受け取ることができるということです。
それはあなたがコルーチンを使用したい場所の簡単な例を思い付くために少し難しいのですが、ここで私の最高の試みです。一例として、この(アップ製)Pythonコードを取ります。
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
コルーチンが使用される場合の一例は、レクサーとパーサです。コルーチンの言語で、または何らかの形でエミュレートしないと、字句や構文解析コードは、彼らが実際には2つの別々の懸念しているにもかかわらず、一緒に混合する必要があります。しかし、コルーチンを使用して、あなたは字句や構文解析コードを分離することができます。
(私は対称および非対称コルーチンの違いを超える磨くつもりだあなたが一方から他方への変換、および非対称コルーチンができ、彼らは同等だと言えば十分 - 。generators-のようなほとんどのですより簡単に理解することが-are。私は1つは、Pythonでの非対称コルーチンを実装する方法を概説した。)
継続は実際には非常にシンプルな獣です。彼らはすべては、あなたがそれを呼び出す場合、実行は自動的にその機能が表すポイントに切り替わることがあります、プログラム内の別のポイントを表す関数です。あなたも、それを実現することなく、毎日それらの非常に制限されたバージョンを使用しています。例外は、例えば、インサイドアウト継続の一種と考えることができます。私はあなたに継続のPythonベースの擬似コードの例をあげるます。
セイPythonはcallcc()
と呼ばれる機能を持っていたし、この関数は2つの引数を取り、最初は関数で、2番目はとそれを呼び出すための引数のリストであること。その機能上の唯一の制限は、それが取る最後の引数は、(私たちの現在の継続となります)関数であろうということでしょう。
def foo(x, y, cc):
cc(max(x, y))
biggest = callcc(foo, [23, 42])
print biggest
何が起こるだろうことはcallcc()
は、現在の継続(foo()
)とターンコールcc
になることで、それは、callcc()
が呼び出されたときのプログラムのポイントへの参照です。 foo()
は現在の継続を呼び出すと、それは基本的にあなたがして、現在の継続を呼んでいる値を返すようにcallcc()
を伝えると同じだし、それがとき、それは、すなわち、現在の継続が作成された場所にスタックをロールバックすることをしたときあなたはcallcc()
と呼ばれます。
このすべての結果は、我々の仮定のPythonの変異体は'42'
を印刷することをでしょう。
私はそれが役に立てば幸い、と私は私の説明がかなり上で改善することができると確信している!
他のヒント
コルーチンは自分の仕事をしてターンを取ると、そのグループ内の他のコルーチンに制御を与えるために一時停止し、いくつかの手順の一つです。
その手続きが行われたときに継続は「関数へのポインタ」であるあなたは(「を継続」)を実行するために、いくつかの手順に渡します。
(.NETで)ジェネレータ値、メソッドの「一時停止」の実行を吐き出した後、次の値を求めたときに、同じ点から進むことができる言語構造である。
はPythonの新しいバージョンでは、Pythonのジェネレータが有効になりますコルーチンれ、generator.send()
でジェネレータに値を送信することができます。
、Pythonで、あなたのyield value
だけ呼び出し元に返すことができるということです。 greenletでいる間、target.switch(value)
は、特定の標的コルーチンにあなたを取るとtarget
を実行し続ける価値を生み出すことができます。