-
tap
はself
を返す。nil
でなければ値を返す。Object#tap {|x| ... } -> self
nil
ならばnil
を返す。NilClass#tap {|x| ...} -> nil
-
tap
ブロックで行った処理は副作用を伴う- 同じオブジェクトに連続的に破壊的代入を行うメソッドチェーンとして利用可能。
P = Struct.new(:name) > P[name = "hoge"].tap{|p| p.name = "fuga"}.tap{|p| p.age = 16} => #<struct P name="fuga", age=16>
-
tap
ブロックはクロージャとして機能する。- 一時変数を必要としない値の入れ替え
> @a = 1 > @a.tap{|x| @a = 2} #=> 1 ... 新しい値(2)で@aを更新し、更新前の値(1)を取り出す。 > @a #=> 2
-
tap
ブロックの結果は無視される(暗黙のignore
(F#))。- printfデバッグ(ruby)
> (-1).tap{|n| if n < 0 then p "negative" else p "positive" end}
- printfデバッグ(Haskell)に相似
import Debug.Trace (trace) debug :: c -> String -> c debug = flip trace isPos :: (Ord a, Num a) => a -> Bool isPos n | n < 0 = False `debug` "negative" | otherwise = True `debug` "positive"
-
tap
ブロックの結果を返すにはbreak
で明示。- 複数の変数・メソッド・返り値などを一度に扱う場合には注意が必要。それぞれで
nil
となる場合を見落としやすい。また、出力の型を定めないと使い勝手の悪いものになる。
> X = Struct.new(:xs) > nil.tap{ |a| break a.xs.compact } # NoMethodError: undefined method `xs' for nil:NilClass > nil.tap{ |a| break a.xs.compact if a } #=> nil > X[xs = nil].tap{ |a| break a.xs.compact if a } # NoMethodError: undefined method `compact' for nil:NilClass > X[xs = nil].tap{ |a| break a.xs.compact if a && a.xs } #=> #<struct X xs=nil> > X[xs = []].tap{ |a| break a.xs.compact if a && a.xs } #=> []
- 型を統一することで以降の
nil
汚染は防げる
> X = Struct.new(:xs) > nil.tap{ |a| break a.xs.compact if a && a.xs; break [] }.map(&:to_s) #=> [] > X[xs = nil].tap{ |a| break a.xs.compact if a && a.xs; break [] }.map(&:to_s) #=> [] > X[xs = [1, nil, 3, 4, nil]].tap{ |a| break a.xs.compact if a && a.xs; break nil }.map(&:to_s) #=> ["1","3","4"]
- 静的型付け言語なら意識する必要はない
> -- f :: Show a => Maybe [Maybe a] -> [String] > let f = maybe [] $ map show . catMaybes > f $ Just [Just 1, Nothing, Just 3, Just 4, Nothing] ["1","3","4"]
- 複数の変数・メソッド・返り値などを一度に扱う場合には注意が必要。それぞれで
Last active
October 21, 2015 23:36
-
-
Save tonosaman/f3a0db303c016b5697e5 to your computer and use it in GitHub Desktop.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment