トップ «前の日記(2007-06-13) 最新 次の日記(2007-06-15)» 編集

じじぃの日記、ツッコミ可

Twitter: @jijixi_org
Xbox Live: jijixi

初心者が書いた OCaml 入門
Spotlight tips サイト内リンク集
1970|01|02|
2003|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|11|
2011|05|
2012|01|

2007-06-14 [長年日記]

% [独り言] あー……あかん、あかんわ……

手応え薄っ。 自分の自己アピール下手には嫌気がさすわ...orz

% [Ruby] 『クロージャによる超軽量並行プロセス』を Ruby で

元ネタはここ

% cat picalc.rb
class Chan
   attr_accessor :state, :val
   def initialize
      @state = :sender
      @val = []
   end
end

def send(y,x)
   case y.state
   when :sender
      y.val << x
   when :receiver
      if y.val.empty?
         y.state = :sender
         y.val = [x]
      else
         f, *rs = y.val
         y.val = rs
         f.call(x)
      end
   else
      raise
   end
end

def recv(y,f)
   case y.state
   when :receiver
      y.val << f
   when :sender
      if y.val.empty?
         y.state = :receiver
         y.val = [f]
      else
         x, *ss = y.val
         y.val = ss
         f.call(x)
      end
   else
      raise
   end
end
irb(main):001:0> require 'picalc'
=> true
irb(main):002:0> x = Chan.new
=> #<Chan:0x41fc8 @state=:sender, @val=[]>
irb(main):003:0> send x, 3
=> [3]
irb(main):004:0> recv x, lambda{|y| p y}
3
=> nil
irb(main):005:0> c = Chan.new
=> #<Chan:0x7b5c0 @state=:sender, @val=[]>
irb(main):006:0> repeat = lambda {
irb(main):007:1*   recv c, lambda{|i| p i; repeat.call}
irb(main):008:1> }
=> #<Proc:0x0004abb4@(irb):6>
irb(main):009:0> repeat.call
=> [#<Proc:0x0004ac2c@(irb):7>]
irb(main):010:0> send c, 1
1
=> [#<Proc:0x0004ac2c@(irb):7>]
irb(main):011:0> send c, 2
2
=> [#<Proc:0x0004ac2c@(irb):7>]
irb(main):012:0> send c, 3
3
=> [#<Proc:0x0004ac2c@(irb):7>]

ここで、ちょっとヤっちまった(謎)ので、仕切り直し。

irb(main):001:0> require 'picalc'
=> true
irb(main):002:0> servc = Chan.new
=> #<Chan:0x41c30 @state=:sender, @val=[]>
irb(main):003:0> serv = Proc.new {
irb(main):004:1*   recv servc, Proc.new{|i, repc|
irb(main):005:2*     send repc, (i * i)
irb(main):006:2>     serv.call
irb(main):007:2>   }
irb(main):008:1> }
=> #<Proc:0x00056cd4@(irb):3>
irb(main):009:0> serv.call
=> [#<Proc:0x00056db0@(irb):4>]
irb(main):010:0> r = Chan.new
=> #<Chan:0x4a114 @state=:sender, @val=[]>
irb(main):011:0> send servc, [123,r]
=> [#<Proc:0x00056db0@(irb):4>]
irb(main):012:0> recv r, Proc.new{|j| p j}
15129
=> nil
irb(main):013:0> send servc, [45,r]
=> [#<Proc:0x00056db0@(irb):4>]
irb(main):014:0> recv r, Proc.new{|j| p j}
2025
=> nil

さっきまで lambda 使ってたのに、突然 Proc.new に変わったのは察してもらいたい。 元のコードに似せようという、涙ぐましい努力なんだよぅ。 最後に fib。

irb(main):015:0> fibc = Chan.new
=> #<Chan:0x54650 @state=:sender, @val=[]>
irb(main):016:0> fib = Proc.new {
irb(main):017:1*   recv fibc, Proc.new{|n, repc|
irb(main):018:2*     fib.call
irb(main):019:2>     if n <= 1
irb(main):020:3>       send repc, n
irb(main):021:3>     else
irb(main):022:3*       repc1 = Chan.new
irb(main):023:3>       repc2 = Chan.new
irb(main):024:3>       send fibc, [n - 1, repc1]
irb(main):025:3>       send fibc, [n - 2, repc2]
irb(main):026:3>       recv repc1, Proc.new{|rep1|
irb(main):027:4*         recv repc2, Proc.new{|rep2|
irb(main):028:5*           send repc, (rep1 + rep2)
irb(main):029:5>         }
irb(main):030:4>       }
irb(main):031:3>     end
irb(main):032:2>   }
irb(main):033:1> }
=> #<Proc:0x000532f0@(irb):16>
irb(main):034:0> fib.call
=> [#<Proc:0x00053368@(irb):17>]
irb(main):035:0> r = Chan.new
=> #<Chan:0x467f8 @state=:sender, @val=[]>
irb(main):036:0> send fibc, [10,r]
=> [55]
irb(main):037:0> recv r, Proc.new{|m| printf "fib(10) = %d\n", 55}
fib(10) = 55
=> nil

send 関数で f.call したときとかの返り値は隠蔽するべきだったと反省した。 この状態だと、recv するまでもなく結果が見えてしまって、ちょっともったいない(苦笑

% [Mac] 思い切って Safari 3 Beta を入れてみた

どうも 2ch の Safari スレとか見るかぎり、SafariStand は微妙っぽい (大丈夫だったりそうでなかったり。有効にしてる機能にもよる?) ので今のところ外した状態。

とりあえず、わしにとって SafariStand で一番重要な機能は、ブックマーク全体のインクリメンタルサーチとブランクリンクをタブに開くことだけど、ブックマークは素でそれができるようになってるので問題無し (キーボードで選択できないから微妙に不便ではあるけど)。 タブの問題は……しばらく我慢。 他の機能は、まあ、無きゃ無いで良いか……くらいのもんなので、当面は気にしない方向で。

2ch では軽くなったっていう意見が大半なんだけど、たしかに軽くなってる気はする。 しばらく、これで過してみる予定。

% [Ruby] 上のネタに関して

なんかちょっと期待されてるみたいなので、わかる範囲で。

とりあえず、上のは、基本的に OCaml の例でやってることを、そのまま書くという意図だったので、あんまり Ruby っぽい書き方じゃないです。 recv の定義をブロックを受け取る形にするなら、こう↓するだけでオッケー。

def recv(y, &f)
   ...

Proc.new と proc と lambda が微妙に違うのがナゼか……は、知りません (駄目だ)。 なんかメーリングリストか何かで見た憶えが微かにあるので、たぶん誰か物覚えの良い人が教えてくれるでしょう (丸投げメソッド)。

% [Ruby] Proc に関するもろもろ

個人的には、

irb(main):001:0> f = Proc.new do |x,y| p x, y end
=> #<Proc:0x0003eae4@(irb):1>
irb(main):002:0> g = proc do |x,y| p x, y end
=> #<Proc:0x0008b3bc@(irb):2>
irb(main):003:0> f.call [1,2]
1
2
=> nil
irb(main):004:0> g.call [1,2]
ArgumentError: wrong number of arguments (1 for 2)
        from (irb):2
        from (irb):4:in `call'
        from (irb):4

こういう二種類の挙動が存在すること自体は悪くないと思う。 で、1.9 でここら辺がいろいろ変わったのは、わかりづらいから…とかじゃなかったかな。 それで、アリティチェックが厳しい Proc#call と、緩い Proc#yield に分かれた……みたいな話だったような気もするけど、記憶が曖昧。 試してみよう。

% irb19
irb(main):001:0> f = Proc.new do |x,y| p x,y end
=> #<Proc:4d4ba8@(irb):1>
irb(main):002:0> g = proc do |x,y| p x,y end
=> #<Proc:4cd650@(irb):2>
irb(main):003:0> f.call [1,2]
1
2
=> nil
irb(main):004:0> g.call [1,2]
1
2
=> nil
irb(main):005:0> f.yield [1,2]
1
2
=> nil
irb(main):006:0> g.yield [1,2]
1
2
=> nil

……あり?

irb(main):007:0> h = lambda do |x,y| p x,y end
=> #<Proc:4b9ba0@(irb):7>
irb(main):008:0> h.call [1,2]
[1, 2]
nil
=> nil
irb(main):009:0> h.yield [1,2]
[1, 2]
nil
=> nil

……なんじゃこりゃ。こんな話だっけ?

irb(main):010:0> f.call 1,2,3
1
2
=> nil
irb(main):011:0> f.yield 1,2,3
1
2
=> nil
irb(main):012:0> g.call 1,2,3
1
2
=> nil
irb(main):013:0> g.yield 1,2,3
1
2
=> nil
irb(main):014:0> h.call 1,2,3
ArgumentError: wrong number of arguments (3 for 2)
        from (irb):14:in `call'
        from (irb):14
        from /usr/local/lib/ruby/1.9/irb.rb:150:in `block (2 levels) in eval_input'
        from /usr/local/lib/ruby/1.9/irb.rb:259:in `signal_status'
        from /usr/local/lib/ruby/1.9/irb.rb:147:in `block in eval_input'
        from /usr/local/lib/ruby/1.9/irb.rb:146:in `eval_input'
        from /usr/local/lib/ruby/1.9/irb.rb:70:in `block in start'
        from /usr/local/lib/ruby/1.9/irb.rb:69:in `catch'
        from /usr/local/lib/ruby/1.9/irb.rb:69:in `start'
        from /usr/local/bin/irb19:13:in `<main>'
irb(main):015:0> h.yield 1,2,3
ArgumentError: wrong number of arguments (3 for 2)
        from (irb):15:in `yield'
        from (irb):15
        from /usr/local/lib/ruby/1.9/irb.rb:150:in `block (2 levels) in eval_input'
        from /usr/local/lib/ruby/1.9/irb.rb:259:in `signal_status'
        from /usr/local/lib/ruby/1.9/irb.rb:147:in `block in eval_input'
        from /usr/local/lib/ruby/1.9/irb.rb:146:in `eval_input'
        from /usr/local/lib/ruby/1.9/irb.rb:70:in `block in start'
        from /usr/local/lib/ruby/1.9/irb.rb:69:in `catch'
        from /usr/local/lib/ruby/1.9/irb.rb:69:in `start'
        from /usr/local/bin/irb19:13:in `<main>'

謎すぎる。これじゃ Proc#yield の存在意義って何さ。 うちの ruby 1.9 がおかしいんかなあ。

ところで、マニュアルの Proc のページで、yield のところに 1.7 feature って書いてあるけど 1.9 の間違いだよね?

% [Mac] Safari 3 のページ内サーチが可愛いすぎる件

基本的には最近の Firefox に付いてるのと同じようなもんなんだけど、マッチした対象の表示のされ方がプリチーすぎる。 これはもう Safari 2 には戻れない(笑

% [Mac] WebKit がバージョンアップしたからといって、システム全体が快適になるなんてことがあり得るだろうか?

や、気のせいかも知んないけど、そんな感じすんのよね。

つーかね、そんなことよりもあれですよ、とうとうバックスラッシュ(もしくは円記号)が化けなくなったみたいよ。

print "hello world\n"

これで、うっかり Safari から tDiary の設定いじっちゃって、正規表現がメタメタになるという悲しい現象からおさらばだ(なんか不毛だな)。

本日のツッコミ(全2件) [ツッコミを入れる]
% TrackBack (2007-06-15 01:37)

http://d.hatena.ne.jp/sukesam/20070615/1181839050<br>jiroの日記<br>『クロージャによる超軽量並行プロセス』を JavaScript で<br> 超軽量プロセスに興味を持ったのでここと、ここを参照してJavaScriptで実装してみた とりあえず、JavaScriptは下のような感じ。 はい。すいません。じじぃさんの丸パクリです。 var Chan = function() { this.state = ”sender”; this.val = []; }; var send = function(y,..

% TrackBack (2007-06-16 01:15)

http://jijixi.azito.com/cgi-bin/diary/index.rb?date=20070615#p01<br>jijixi's diary<br>[Ruby] 『『クロージャによる超軽量並行プロセス』を Ruby で』をもう少し Ruby っぽく<br>昨日の続き。 % cat picalc2.rb class Chan def initialize @receive = false @val = [] end def &lt;&lt;(x) unless @receive @val &lt;&lt; x else if @val.empty? @receive = !@receive @val = [x] else f, *rs = @val @val = rs f.call(x) end end self end alias :send..

お名前:
E-mail:
コメント:

トップ «前の日記(2007-06-13) 最新 次の日記(2007-06-15)» 編集

日記ってのは本来、自分で読み返すためにあるもんだよなあ……
もしくは有名人になったら死後に本になったりとかか?

RSS はこちら

jijixi at azito.com