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

パターンマッチと右代入が便利になる gem をつくった

osyo
November 05, 2020

パターンマッチと右代入が便利になる gem をつくった

osyo

November 05, 2020
Tweet

More Decks by osyo

Other Decks in Programming

Transcript

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

    Ruby にパッチを投げたり bugs.ruby で気になったチケットを ブログにまとめたりしてる Ruby 2.5 〜 2.7 までオレオレ機能を追加した Ruby 3.0 では機能追加できなかった… Ruby で⼀番好きな機能は Refinements オンラインなのであちこちの地域.rb に参加してる @pink_bangbi osyo-manga Secret Garden(Instrumental) Fukuoka.rb Hamada.rb kawasaki.rb nikotama.rb Sendai.rb Shibuya.rb Shinjuku.rb Tama.rb Toyama.rb Gotanda.rb Entaku.rb Grow.rb Hamamatsu.rb kanazawa.rb Kobe.rb Machida.rb mitaka.rb Ruby Tuesday toruby ⻄⽇暮⾥.rb
  2. Ruby 2.7 / 3.0 でパターンマッチが⼊った Ruby 2.7 / 3.0 でパターンマッチが⼊った

    Ruby 2.7 / 3.0 でパターンマッチが⼊りました これは以下のような感じで使うことができる def check(user) case user in { name:, age: (..20) } "#{name} は魔法少⼥です" in { name:, age: (20..) } "#{name} は魔法少⼥ではありません" else " わからない" end end p check({ name: " ほむ", age: 14 }) # => " ほむは魔法少⼥です" p check({ name: " マミ", age: 30 }) # => " マミは魔法少⼥ではありません" p check([" まどか", 14]) # => " わからない"
  3. 任意のクラスでパターンマッチできる 任意のクラスでパターンマッチできる #deconstruct_keys を定義することで拡張できる class Time # in に書いた Hash

    のキーを受け取る # 返した Hash でパターンマッチを⾏う def deconstruct_keys(keys) { year: year, month: month, day: day } end def to_four_seasons case self in { month: (3..5) } then "spring" in { month: (6..8) } then "summer" in { month: (9..11) } then "autumn" in { month: (1..2) } | { month: 12 } then "winter" end end end p Time.now.to_four_seasons # => "autumn"
  4. 応⽤するとこんな事ができる 応⽤するとこんな事ができる module PatternMatchWithMethod # メソッドを呼び出すような拡張を⾏う def deconstruct_keys(keys) keys.to_h {

    |name| [name, public_send(name)] } end end class Time include PatternMatchWithMethod def to_four_seasons case self in { month: (3..5) } then "spring" in { month: (6..8) } then "summer" in { month: (9..11) } then "autumn" in { month: (1..2) } | { month: 12 } then "winter" end end end p Time.now.to_four_seasons # => "autumn"
  5. いろいろと便利に使える class Array include PatternMatchWithMethod end # 配列のメソッドの結果を取得する case ["homu",

    "mami", "mado"] in { first:, last:, size: } end p first # => "homu" p last # => "mado" p size # => 3 # インスタンスに extend して⽣やすこともできる case { name: "homu", age: 14 }.extend PatternMatchWithMethod in { keys:, values: } end p keys # => [:name, :age] p values # => ["homu", 14]
  6. pattern_matchable pattern_matchable require "pattern_matchable" class Time # PatternMatchable を include

    するとすぐに使える include PatternMatchable def to_four_seasons case self in { month: (3..5) } then "spring" in { month: (6..8) } then "summer" in { month: (9..11) } then "autumn" in { month: (1..2) } | { month: 12 } then "winter" end end end p Time.now.to_four_seasons # => "autumn"
  7. using PatternMatchable するだけで拡張できる using PatternMatchable するだけで拡張できる require "pattern_matchable" # このファイル内でのみ反映される

    using PatternMatchable class Time def to_four_seasons case self in { month: (3..5) } then "spring" in { month: (6..8) } then "summer" in { month: (9..11) } then "autumn" in { month: (1..2) } | { month: 12 } then "winter" end end end p Time.now.to_four_seasons # => "autumn" case ["homu", "mami", "mado"] in { first:, last:, size: } end p [first, last, size] # => ["homu", "mado", 3]
  8. 特定のクラスのみ拡張もできる 特定のクラスのみ拡張もできる require "pattern_matchable" class Time # Time クラスのみ拡張する using

    PatternMatchable Time def to_four_seasons case self in { month: (3..5) } then "spring" in { month: (6..8) } then "summer" in { month: (9..11) } then "autumn" in { month: (1..2) } | { month: 12 } then "winter" end end end p Time.now.to_four_seasons # => "autumn" # Array は拡張されない # error: ["homu", "mami", "mado"] (NoMatchingPatternError) case ["homu", "mami", "mado"]
  9. ちなみにパターンマッチなので以下のように書くこともできる homu = { name: "homu", age: 14 } #

    特定のクラスのみ代⼊できる homu => { name: String => name, age: Integer => age } p [name, age] # => ["homu", 14] mami = { name: :mami, age: 14 } # これはエラー # error: {:name=>:mami, :age=>14} (NoMatchingPatternError) mami => { name: String => name, age: Integer => age } p [name, age] # => ["homu", 14]
  10. まとめ まとめ Ruby 2.7 / 3.0 でパターンマッチという機能が実装された パターンマッチ便利 パターンマッチは #deconstruct_keys

    を定義することで任意のクラス をパターンマッチすることができる を使うと簡単に既存のクラスを拡張できるよ Refinements は最⾼だな!! 右代⼊も最⾼だな!! pattern_matchable
  11. 宣伝 宣伝 今週の⾦曜⽇だよ! yukicoder の問題をみんなで解いてみるよ! 今年もやるよ!!! みんな参加してね! Ruby 3.0 についての

    Advent Calendar だよ!!! 寂しいのでみんな参加してね!! 参加して!!! Machida.rb #07 - Machida.rb | Doorkeeper Ruby Advent Calendar 2020 Ruby 3.0 Advent Calendar 2020 令和時代の基礎⽂法最速マスター