Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Proc#using 感想戦

osyo
September 25, 2020

Proc#using 感想戦

osyo

September 25, 2020
Tweet

More Decks by osyo

Other Decks in Technology

Transcript

  1. ⾃⼰紹介 ⾃⼰紹介 名前:osyo Twitter : github : ブログ : 趣味で

    Ruby にパッチを投げたり bugs.ruby で気になったチケットを ブログにまとめたりしてる Ruby で⼀番好きな機能は Refinements @pink_bangbi osyo-manga Secret Garden(Instrumental)
  2. Refinements とは Refinements とは 特定のコンテキストでのみクラス拡張を適⽤する構⽂ 通常のモンキーパッチとは違い名前衝突の危険性を最⼩限に抑え、 安全にクラス拡張する事ができる module Twice #

    String に新しいメソッドを定義する # これだけでは定義されない refine String do def twice self + self end end end # using を呼び出したコンテキストでのみメソッドが適⽤される using Twice p "homu".twice # => "homuhomu"
  3. Proc#using とは Proc#using とは Proc#using は任意のブロックに対して using を⾏う機能になる これを利⽤することで任意のブロック内でのみメソッド拡張を適⽤ する事ができる

    # これを using したコンテキストのみ Proc#using が利⽤できる using Proc::Refinements block = proc { p "homu".twice } # ブロックに対して using を⾏うと # そのブロック内で Twice が適⽤される block.using Twice block.call # => "homuhomu"
  4. Proc#using を利⽤するとメソッドに渡したブロック内で暗黙的にク ラス拡張を適⽤する事ができる # ブロックに対して任意の Refinements を適⽤できる def benri(&block) block.using

    Twice block.call end using Proc::Refinements # ブロック内で独⾃のメソッド拡張が呼べる benri { p "homu".twice p "mami".twice.twice } # ブロックの外では使えない # error: : undefined method `twice' for "mado":String (NoMethodError) p "mado".twice
  5. Proc#using 感想 Proc#using 感想 Refinements は using とワンセットで使う機能になる ユーザは明⽰的に『どの拡張を⾏うのか』を指定して使う ⼀⽅で

    Proc#using の場合は using するモジュールが定義側で隠蔽さ れてしまう ブロックを書くユーザ側ではどのモジュールが拡張されるのか不 透明になる それはユーザの意図しないメソッドが呼び出される可能性があるの で危険なのではないだろうか 個⼈的にはユーザ側でどのモジュールが適⽤されるのかを明⽰化し たい # ブロック内で何が using されているのかがわからない… benri { p "homu".twice }
  6. そもそも そもそも ブロック内のコンテキストが変わってしまうのは instance_eval を使 ったときでも同じ ブロック内で self が変わってしまうことはよくある なので

    Proc#using で呼び出されるメソッドが意図しない云々は今更 感がある どうしても気になるなら Proc#using を使って便利メソッドを定義す ればいい # Proc#using を使ったヘルパメソッドを定義してやる def using_local(mod, &block) block.using mod block.call end using Proc::Refinements # モジュールを渡して using を明⽰化する using_local(Twice) { p "homu".twice }
  7. 仮に using_local みたいなメソッドがあったとしてもメソッド内で隠 蔽されてしまえば結局 Proc#using と同じ問題に突き当たる Proc#using だけを⾒ると使い⽅に関して気になる点はあるが利便性 を考えるとめっちゃほしい!!! def

    benri(&block) # ブロック内で using_local を経由してブロックが呼びされたら # 結局使う側からはどのモジュールが using されるのかは不透明になる using_local(Twice, &block) end # 結局どのモジュールが適⽤されているのかがわからない benri { p "homu".twice p "mami".twice.twice }
  8. まとめ まとめ Proc#using ⾃体に関しては書き⽅や使い⽅に関してちょっと気にな る部分がある が、それ以上に Proc#using 便利なのでほしい!!! Proc#using に関しては結構省いた部分があるので詳しくは元のセッ

    ションを⾒てください Refinements どちゃくそ便利なのでみんなどんどん Refinements を使 ってくれー!! あとバグがあったらどんどん報告してくれー!!!