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

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

Avatar for osyo osyo
November 05, 2020

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

Avatar for osyo

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 令和時代の基礎⽂法最速マスター