query: tag:callcc

メソッドやProcの内部で継続(Continuation)を実行した後に、
そのメソッドの戻り値がどうなるのか理解があやふやだったので実験。

前準備。
ruby>>
a = nil
foo = proc{callcc{|a|}; 1}
bar = proc{foo.call; 2}
baz = proc{a.call; 3}
<<--

実験開始。

ruby>>

foo.call
=> 1

baz.call
=> 1

bar.call
=> 2

baz.call
=> 2
<<--

なるほど。

posted by genki genki on Sat 5 Jul 2008 at 04:05 with 0 comments

I made a small utility library named
Wormhole.
The library enables us to communicate between caller and callee.

Here is a simple example of use.

ruby>>
require 'rubygems'
require 'wormhole'

def foo(array)
array << :foo # (1)
Wormhole.throw array
array << :baz # (3)
end

result = Wormhole.catch do
foo []
end.return do |array|
array << :bar # (2)
end
puts result.inspect # => [:foo, :bar, :baz]
<<--

First, the block passed to Wormhole.catch, the caller, is evaluated.
The foo method, the callee, throw an array object passing through the wormhole.
Then the array is caught by the last block passed to a return method. A block parameter of the block is the array.
Finally, the process goes back to the point 3 after the last block ends.
A return value of the foo method is returned via the return method.

By using this utility, you can participate to a depth of a complicated system from a safer position.

At the end, you can install this utility from the GitHub by using gem command like this.

pre>>
% sudo gem sources -a http://gems.github.com
% sudo gem install genki-wormhole
<<--

Have fun!

posted by takiuchi takiuchi on Sat 5 Jul 2008 at 01:51 with 2 comments

ちょっと必要に駆られて、
Wormhole
というライブラリを書きました。

350px-Worm3.jpg

インストールはGitHubから行えます。

pre>>
sudo gem sources -a http://gems.github.com
sudo gem install genki-wormhole
<<--

メソッドの内部を実行中に、呼び出し元に一旦処理を戻し、
中断した場所から処理を継続する機能を提供します。

例えば、以下のようなプログラムに対して、

ruby>>
require 'rubygems'
require 'wormhole'

def foo
puts "foo"
Wormhole.throw :foo => 'hello' do |data|
puts data[:foo]
end
puts "bar"
end

Wormhole.catch do
foo
end.return do |data|
puts data[:foo]
data[:foo] = 'world!'
end
<<--

結果として、以下のような出力を得ます。

pre>>
foo
hello
world!
bar
<<--

処理を中断したいところで Wormhole.throw を呼び出して、
外側から Wormhole.catch で受け止めます。
catchが完了したら、Wormholeオブジェクトが返るので、
returnで中断箇所に戻ります。
Wormhole.throw はHashを受け渡すことができます(省略可能)。
また、catchブロックとreturnは上記の例のように続けて記述します。
catchの戻り値を適当な変数に代入して、後でreturn
を呼び出すことも可能ですが、その場合、catchを抜けた直後から
returnを呼ぶまでの区間が二度実行されてしまいます
(この辺が最初に例外を使って実装してた理由ですね)

中断箇所から処理を再開するために callcc を使っています。
callccは面白いですね。

更新履歴

  • 2008/7/4 例外処理をやめてthrow/catchを使うようにしました。それにあわせて本文を修正しました。
posted by genki genki on Thu 3 Jul 2008 at 21:08 with 5 comments