RSpecのexpectが
a = -> { } # 本当のソースはlet使ったけど
expect(a)
expect(&a)
というようにa
でも&a
でもどちらでも渡せたのでどうやるのかと思って、
自分で書いてみた。(RSpecのexpectと同じかどうかは知らない)
下記 piyo
に注目。a
でも&a
でもどちらでも渡せた。さらに{ }
の形式でも渡せる。
上記サンプルに書かなかったが、expect
も{ }
で渡せる。
a = -> { p 'AA' }
def hoge(procedure)
procedure.call
end
def foo(&procedure)
procedure.call
end
def piyo(procedure = nil, &procedure2)
if block_given?
procedure2.call
else
procedure.call
end
end
##############################
# ここから呼び出し処理
##############################
hoge(a)
# hoge(&a) #=> 無理
# hoge { 'BB' } #=> 無理
foo(&a) #=> foo(a) はできない
foo { p 'BB' }
piyo(a)
piyo(&a)
piyo { p 'CC' }
出力結果
"AA"
"AA"
"BB"
"AA"
"AA"
"CC"
piyoをRubyぽく書き直す
ということでpiyo関数をさらに発展させる。
どう発展させるかというとRubyの機能を使ってRubyぽく書き直す。
この発展させた関数をfugaとしたのが下記ソース。
yield
を使えば第2引数を書く必要がなくなった。
a = -> { p 'AA' }
def fuga(procedure = nil)
if block_given?
yield
else
procedure.call
end
end
fuga(a)
fuga(&a)
fuga { p 'CC' }
.call のシンタックスシュガー .() を使う
.callはシンタックスシュガーがあるので下記のように書き換えれる
a = -> { p 'AA' }
def fuga(procedure = nil)
if block_given?
yield
else
procedure.() # シンタックスシュガー
end
end
fuga(a)
fuga(&a)
fuga { p 'CC' }
じゃあ明示的に第2引数(最後にブロックを受け取る引数)を書きたいときはどんなとき?
受けっとた手続きをさらに別の引数に渡したいときに明示的に変数に入れたいのでこの場合は第2引数を書くらしい。
def my_map(procedure = nil, &procedure2)
r = if block_given?
(0..2).map(&procedure2) #=> ここでさらに別のメソッドの引数に渡している
else
(5..7).map(&procedure)
end
p r.to_a
end
a = ->(v){v}
my_map(a)
my_map(&a)
my_map {|v| v * 2}
結果:
[5, 6, 7]
[0, 1, 2]
[0, 2, 4]