Rubyの魔神 このページをアンテナに追加 RSSフィード

   「Ruby」は宝石の魔神のイメージ(The Jinn of the Ruby)
   [VB] [VB6] [C#] [Android] [電子工作] [個人メモ] [仕事メモ] [アイデア] [TstLink] [CE] [LTSA] [自動化] [Qt] [OCaml] [TOOLS]
   [3Dプリンタ] [RAA] [Forge]   [機能別索引] [逆引きRuby] [マニュアル] [るびま] [標準ライブラリ] [るりまサーチ] [Try! Ruby] [PRaggerまとめ] [ピジョン・ブラッド]
   [Rubyコーディング規約] [プログラミングのオキテ] [Rubyist SNS] [TOOLBIS]
   [RubyネットワークProg] [druby] [コードなにがし] [RDocテンプレ] [Ruby/Tkサンプル]
   [WAVE] [Xperia] [github] [twitterなど] [Java] [EA] [マクロ]

2013-09-23

rubyでチャーチ数

rubyでチャーチ数 - Rubyの魔神 を含むブックマーク はてなブックマーク - rubyでチャーチ数 - Rubyの魔神 rubyでチャーチ数 - Rubyの魔神 のブックマークコメント

http://uid0130.blogspot.jp/2013/05/x.html#Message-complete

上記を参考にλのチャーチ数,true,false,if等をrubyで書いてみる。

そのままだと名前がかぶる名前は以下頭に_をつける。

#1.チャーチ数

#0 = λfx. x
zero = ->f,x{x}
#1 = λfx. f x
one = ->f,x{f[x]}
#2 = λfx. f (f x)
two = ->f,x{f[f[x]]}
#3 = λfx. f ( f (f x) )
three = ->f,x{f[f[f[x]]]}

inc = -> x{x+1} #チャーチ数-自然数 変換表示用

puts zero[inc,0]#=>0
puts one[inc,0]#=>1
puts two[inc,0]#=>2

#インクリメント(succ)
#succ = λnfx. f(n f x)
succ = -> n,f,x {f[n[f,x]]}
puts "succ"
puts succ[three,inc,0]#=>4

#足し算
#plus = λmnfx. m f (n f x)
plus = -> m,n,f,x{m[f,n[f,x]]}

#1+2
puts "plus"
puts plus[one,two,inc,0]#=>3

#2.分岐構造
#true = λxy. x
#false = λxy. y
#if = λcxy. c x y

_true = ->x,y{x}
_false = ->x,y{y}
_if = ->c,x,y{c[x,y]}

puts "if"
puts _if[_true,"TRUE","FALSE"] #=>"TRUE"
puts _if[_false,"TRUE","FALSE"] #=>"FALSE"

#3.論理式
#not = λx. x false true
#and = λxy. x y false
#or = λxy. x true y
#xor = λxy. x (not y) y

_not =->x {x[_false,_true]}

puts "not"
puts _if[_not[_true],"TRUE","FALSE"] #=>"FALSE"
puts _if[_not[_false],"TRUE","FALSE"] #=>"TRUE"

puts "and"
_and = ->x,y{x[y,_false]}
puts _if[_and[_true,_true],"TRUE","FALSE"] #=>"TRUE"
puts _if[_and[_false,_true],"TRUE","FALSE"] #=>"FALSE"
puts _if[_and[_true,_false],"TRUE","FALSE"] #=>"FALSE"
puts _if[_and[_false,_false],"TRUE","FALSE"] #=>"FALSE"

puts "or"
_or = ->x,y{x[_true,y]}
puts _if[_or[_true,_true],"TRUE","FALSE"] #=>"TRUE"
puts _if[_or[_false,_true],"TRUE","FALSE"] #=>"TRUE"
puts _if[_or[_true,_false],"TRUE","FALSE"] #=>"TRUE"
puts _if[_or[_false,_false],"TRUE","FALSE"] #=>"FALSE"

puts "xor"
_xor = ->x,y{x[_not[y],y]}
puts _if[_xor[_true,_true],"TRUE","FALSE"] #=>"FALSE"
puts _if[_xor[_false,_true],"TRUE","FALSE"] #=>"TRUE"
puts _if[_xor[_true,_false],"TRUE","FALSE"] #=>"TRUE"
puts _if[_xor[_false,_false],"TRUE","FALSE"] #=>"FALSE"

#4.数値判定
#iszero? = λz. z (λx. false) true

iszero = -> z{z[->x{_false},_true]}
puts "iszero"
puts _if[iszero[zero],"TRUE","FALSE"] #=>"TRUE"
puts _if[iszero[one],"TRUE","FALSE"] #=>"FALSE"

引数無しのlambda式

引数無しのlambda式 - Rubyの魔神 を含むブックマーク はてなブックマーク - 引数無しのlambda式 - Rubyの魔神 引数無しのlambda式 - Rubyの魔神 のブックマークコメント

引数無しのlambda式を考えてみた

->{puts 7}

定義出来るみたい。

空の引数を与えると実行もできた

->{puts 7}[]#=> 7 とnil

a=->{puts 8}
a[]#=> 8 とnil

BlockとProc

BlockとProc - Rubyの魔神 を含むブックマーク はてなブックマーク - BlockとProc - Rubyの魔神 BlockとProc - Rubyの魔神 のブックマークコメント

procに&をつけるとBlockになるけど、

Proc.newブロック

procブロック

以外でブロックをprocに変換する方法はあるのだろうか。

Procとyield

Procとyield - Rubyの魔神 を含むブックマーク はてなブックマーク - Procとyield - Rubyの魔神 Procとyield - Rubyの魔神 のブックマークコメント

def func1
  x="func1"
  yield(x)
  yield(x)
end

func1 {|x|puts "#{x}"}

これは以下のように書ける。

def func2(&p)
  x="func2"
  p[x]
  p[x]
end

func2 {|x|puts "#{x}"}

つまりデフォルトで用意されたProc型のyieldに引数を与えて実行したものになる。

Ruby始めた頃は何も考えずに丸暗記してyield使ってたけど、元々こういう意味みたい。


ラムダ式で書くとこんな感じになる。

func3 = -> p {
  x = "func3"
  p[x]
  p[x]
}

func3[proc{|x|puts "#{x}"}]

引数で渡すブロックもラムダ式で書くとこんな感じになる。


func3 = -> p {
  x = "func3"
  p[x]
  p[x]
}

p1 = ->x { puts "#{x}"}

func3[p1]
func3[->x { puts "#{x}"}]

func3[proc{|x|puts "#{x}"}] procの場合

func3[->x { puts "#{x}"}] ->の場合

引数を持つ関数を与えて引数に何か代入させて実行するわけですね。

トラックバック - http://ruby.g.hatena.ne.jp/garyo/20130923