PythonのyieldをJavaやJavaScriptで表現するにはどうすればいいのかを考えてみました。
今回は実用的に何か作ってみたというのではなく、コードジェネレーターをなどを作るとすればどう置き換えればいいのかを考えてみたというレベルなのであしからずです。
とりあえず、これを題材にしてみました。
# your code goes here
def Generator(n):
yield 1;
idx = 0
while idx < n:
yield 2
idx += 1
yield 3
g = Generator(5)
for x in g:
print x
ちょっと考えた方針
- ループはgoto文のようなもので置き換え可能
- while文とswitch文を組み合わせればgoto文を表現可能
- yieldした位置をstateとして保存しておく
この方針でJavaScriptで書いてみました。
// your code goes here
function Generator(n) {
var ctx = { state:0, idx:0 };
return function() {
while (1) {
switch (ctx.state) {
case 0:
ctx.state = 1;
return 1;
case 1:
if (ctx.idx < n) {
ctx.idx++;
return 2;
}
ctx.state = 2;
break;
case 2:
ctx.state = -1;
return 3;
default:
return undefined;
}
}
};
}
(function() {
var g = Generator(5);
while (1) {
var x = g();
if (x === undefined)
break;
print(x);
}
})();
同様にJavaで書いてみました。
/* package whatever; // don't place package name! */
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
private static class Generator {
final int n_;
int state_ = 0, idx_ = 0;
boolean completed_ = false;
Generator(int n) {
n_ = n;
}
int generate() {
while (true) switch (state_) {
case 0:
state_ = 1; return 1;
case 1:
if (idx_ < n_) {
idx_++;
return 2;
}
else {
state_ = 2;
}
break;
case 2:
completed_ = true;
return 3;
}
}
boolean isCompleted() { return completed_; }
}
public static void main (String[] args) throws java.lang.Exception
{
Generator g = new Generator(5);
while (! g.isCompleted()) {
int x = g.generate();
System.out.println(x + "");
}
}
}
どちらも一応目的の動きはしています。
こんなコードジェネレーターはすでにあるんでしょうか。
世の中でブラウザでyield文が普通に使える時代になればこんなことは考えなくてすみますね。