Skip to content

Instantly share code, notes, and snippets.

@tonosaman
Last active October 21, 2015 23:36
Show Gist options
  • Save tonosaman/f3a0db303c016b5697e5 to your computer and use it in GitHub Desktop.
Save tonosaman/f3a0db303c016b5697e5 to your computer and use it in GitHub Desktop.

(Ruby)tap

  • tapself を返す。

  • 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"]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment