Fiber $B$b$I$-(B for 1.8.x

岩室です。

1.9.0-2見るまで知らなかったのですが、Generator消えるんですね。

まだ1.8ユーザですが、単に消えられるとちょっと困るので、callcc
を使って1.8にFiberもどき(もがき)を書いてみたのですが、如何でしょう?
全く同じ動作にはできなかったのですが、Generatorの代替ならこれでいいかな、と……。
callcc ã®æŒ¯ã‚‹èˆžã„ã«é ­ãŒæ··ä¹±ã—ã¦ã‚‹ã®ã§ä½•ã‹ãƒ¯ãƒŠãŒã‚ã‚‹ã‹ã‚‚ã—ã‚Œã¾ã›ã‚“ãŒã€‚
実験的に書いたので日本語コメントが入りまくっています。
なお、test_fiber18.rb は1.9ã‹ã‚‰ã‚‚ã‚‰ã£ã¦ãã¦æ‰‹ã‚’åŠ ãˆãŸã‚‚ã®ã§ã™ã€‚

e$B$J$+$@$G$9!#e(B

At Sat, 5 Jul 2008 14:09:25 +0900,
IWAMURO Motonori wrote in [ruby-dev:35369]:

1.9.0-2e$B8+$k$^$GCN$i$J$+$C$?$N$G$9$,!"e(BGeneratore$B>C$($k$s$G$9$M!#e(B

e$B$^$@e(B1.8e$B%f!<%6$G$9$,!"C1$K>C$($i$l$k$H$A$g$C$H:$$k$N$G!"e(Bcallcc e$B$r;H$C$Fe(B1.8e$B$Ke(BFibere$B$b$I$-e(B(e$B$b$,$-e(B)e$B$r=q$$$F$_$?$N$G$9$,!"G!2?$G$7$g$&e(B?
e$BA4$/F1$8F0:n$K$O$G$-$J$+$C$?$N$G$9$,!“e(BGeneratore$B$NBeBX$J$i$3$l$G$$$$$+$J!”$H!D!D!#e(B

e$B40A4$KF1$8$G$O$"$j$^$;$s$,!"e(BGeneratore$B$NBeBX$H$7$F$Oe(B
Enumerator#nexte$B$,;H$($k$O$:$G$9!#e(B

e$B$H$$$&$+e(BGeneratore$B$NBe$o$j$Ke(BFibere$B$r!"$H$$$&N.$l$,IT;W5D$J$s$G$9$,!#e(B

e$B1sF#$G$9!#e(B

2008/07/05 14:09 IWAMURO Motonori [email protected]:

1.9.0-2e$B8+$k$^$GCN$i$J$+$C$?$N$G$9$,!"e(BGeneratore$B>C$($k$s$G$9$M!#e(B

e$B$^$@e(B1.8e$B%f!<%6$G$9$,!"C1$K>C$($i$l$k$H$A$g$C$H:$$k$N$G!"e(Bcallcc e$B$r;H$C$Fe(B1.8e$B$Ke(BFibere$B$b$I$-e(B(e$B$b$,$-e(B)e$B$r=q$$$F$_$?$N$G$9$,!"G!2?$G$7$g$&e(B?

e$B5U$K!"e(BFiber e$B$r;H$C$Fe(B 1.9 e$BMQ$Ke(B generator.rb
e$B$r=q$$$F$_$^$7$?!#e(B
e$BB(6=$G=q$$$?$N$G??LLL$K8!>Z$7$F$J$$$G$9$,!"e(B1.8 e$B$Ne(B
generator.rb e$B$Ke(B
e$BIUB0$7$F$$$?%F%9%H$O%Q%9$7$^$7$?!#e(B

class Generator
include Enumerable

def initialize(enum = nil, &block)
@block = enum ? proc {|g| enum.each {|x| g.yield(x) } } : block
@fiber = Fiber.new { @block.call(self); @fiber = nil }
@index = 0
@queue = []
@fiber.resume
end

def yield(value)
@queue << value
Fiber.yield(value)
end

def end?
@fiber.nil? && @queue.empty?
end

def next?
!end?
end

def index
@index
end
alias pos index

def next
raise(EOFError, “no more elements available”) if end?
@fiber.resume
@index += 1
@queue.shift
end

def current
raise(EOFError, “no more elements available”) if @queue.empty?
@queue.first
end

def rewind
initialize(nil, &@block) if @index.nonzero?
self
end

def each
rewind
yield self.next until end?
self
end
end

e$B4d<<$G$9!#e(B

2008/07/06 15:32 Nobuyoshi N. [email protected]:

e$B40A4$KF1$8$G$O$"$j$^$;$s$,!"e(BGeneratore$B$NBeBX$H$7$F$Oe(B
Enumerator#nexte$B$,;H$($k$O$:$G$9!#e(B

e$B:Q$$^$;$s!“%^%K%e%”%k$r$"$5$C$F$$?$s$G$9$,!"e(BGeneratore$BIw$N;H$$J}$,A4$/$o$+$j$^$;$s$G$7$?!#e(B
e$B$d$j$?$$$3$H$O$3$s$J46$8$N$3$H$G$9$,!"e(BEnumeratore$B$G$O$I$&=q$1$P$$$$$s$G$7$g$&!#e(B

Generatore$B$N%V%m%C%/$NCf$G$N=hM}7k2L$r!"e(B

g = Generator.new{|g| IO.popen(“tar --help”) {|io| io.each_line
{|line| g.yield(line)}}}

e$B$I$3$+1s$/$N$H$3$m$G<hF@$7$?$$e(B

while g.next?; io.print(g.next); end

e$B$H$$$&$+e(BGeneratore$B$NBe$o$j$Ke(BFibere$B$r!"$H$$$&N.$l$,IT;W5D$J$s$G$9$,!#e(B

e$B<B$O<j85$Ke(BFibere$B$G=q$-D>$7$?e(Bgenerator.rbe$B$b$“$C$?$s$G$9$,!D!D!#=q$/$N$O$9$4$/4JC1$@$C$?$N$Ke(B
e$B>C$($F$?$N$G!“2?$+M}M3$,$”$k$N$+$H;W$C$F2a5n%a!<%k$r$”$5$C$F$_$?$H$3$m!"e(B[ruby-dev:34278]
e$B$NN.$l$r8+$F!Ve(BGeneratore$B$O>C$7$^$7$g$&!W$H$$$&$N$,%3%s%;%s%5%9$J$N$+$H;W$C$?$N$G$7$?!#e(B

e$B$G!“$I$&$;:#$+$i=q$/$N$J$ie(BFibere$B$G=q$$$F$*$1$P>-Mh$N0\9T$N$H$-$K9M$($J$/$F$$$$$s$8$c$J$$$+e(B
e$B$H$$$&$3$H$G!”>/$J$/$H$b>e$NNc$G=q$$$?$h$&$J$3$H$,$G$-$kDxEY$N5!G=$r<BAu$7$F$_$?$N$,!"e(B
e$B7o$N%3!<%I$G$9!#e(B