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

読めるかな?ちょっとレアなRubyの記法

 読めるかな?ちょっとレアなRubyの記法

北陸三県.rb Lightning Talks in Kanazawa (2025/01/18) の発表資料。
Ruby 3.4 で追加となった it 記法を皮切りに、いくつかのちょっと珍しい「書き方」をご紹介する。

Avatar for Tomokazu Kiyohara

Tomokazu Kiyohara

January 18, 2025
Tweet

More Decks by Tomokazu Kiyohara

Other Decks in Programming

Transcript

  1. it is "default block parameter" ref. Fe a ture #18980:

    `it` a s a def a ult block p a r a meter - Ruby m a ster - Ruby Issue Tr a cking System ( https://bugs.ruby-l a ng.org/issues/18980 )
  2. "σϑΥϧτ" ϒϩοΫύϥϝʔλ [1, 2, 3].map {|i| i * 10 }

    [1, 2, 3].map { it * 10 } #=> [ 10, 20, 30 ]
  3. "σϑΥϧτ" ϒϩοΫύϥϝʔλ [1, 2, 3].map {|i| i * 10 }

    [1, 2, 3].map { it * 10 } #=> [ 10, 20, 30 ]
  4. it ͝࢖༻্ͷ஫ҙʹ͍ͭͯ [1, 2, 3].map { it * 10 }

    #=> [ 10, 20, 30 ] it = 9 [1, 2, 3].map { it * 10 } #=> [ 90, 90, 90 ] ϒϩοΫ֎Ͱ it Λఆ͍ٛͯ͠Δͱ ϒϩοΫ಺ͷ it ͸౰֘ม਺ͱͯ͠ॲཧ͞ΕΔ
  5. • αϯϓϧίʔυͰΘ͔ΔʂRuby 3.4ͷओͳ৽ػೳͱมߋ఺ P a rt 2ɾ৽ ػೳͱมߋ఺ͷ૯·ͱΊ #R a

    ils - Qiit a • https://qiit a .com/jnchito/items/ e a db5f96e0fd ff 01bd71#%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E3%81%AE%E3 %83%96%E3%83%AD%E3%83%83%E3%82%AF%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%8 2%BF%E3%81%A8%E3%81%97%E3%81%A6-it- %E3%81%8C%E8%BF%BD%E5%8A%A0%E3%81%95%E3%82%8C%E3%81%9F • ϓϩͱಡΈղ͘Ruby 3.4 NEWS - STORES Product Blog • https://product.st.inc/entry/2024/12/25/154728 it ਂ۷Γ
  6. numbered block parameter (Ruby 2.7 ~) ref. Ruby 2.7 ch

    a nges - Ruby Ch a nges ( https://rubyreferences.github.io/rubych a nges/2.7.html#numbered-block-p a r a meters )
  7. • Ruby: "uselessγϯλοΫεγϡΨʔ"γϦʔζ: numbered block p a r a metersʢ຋༁ʣʛTechR

    a cho by BPSגࣜձࣾ • https://techr a cho.bpsinc.jp/h a chi8833/2024_01_22/136901 numbered block parameter ਂ۷Γ
  8. % ه๏ ref. Ϧςϥϧ (Ruby 3.4 ϦϑΝϨϯεϚχϡΞϧ) ( https://docs.ruby-l a

    ng.org/j a /l a test/doc/spec=2 f liter a l.html#percent )
  9. % ه๏ % %Q %(a b #{1 + 2}) %Q(a

    b #{1 + 2}) "a b #{1 + 2}" "a b 3" %q %q(a b #{1 + 2}) 'a b #{1 + 2}' "a b \#{1 + 2}" %x %x(ls -a) `ls -a` ".\n..\n.git\nREADME\n" %r %r([A-z]+$) /[A-z]+$/ /[A-z]+$/ %w %w(a b #{1 + 2}) ['a', 'b', '#{1', '+', '2}'] ["a", "b", "\#{1", "+", "2}"] %W %W(a b #{1 + 2}) ["a", "b", "#{1 + 2}"] ["a", "b", "3"] %s %s(a b #{1 + 2}) :'a b #{1 + 2}' :"a b \#{1 + 2}" %i %i(a b #{1 + 2}) [:a, :b, :'#{', :+, :'2}'] [:a, :b, :"\#{", :+, :"2}"] %I %I(a b #{1 + 2}) [:a, :b, :"#{1 + 2}"] [:a, :b, :"3"]
  10. % ه๏ • ΤεέʔϓॲཧΛল͚Δͷ͕ར఺ • ॻ͖΍͢͞ͱ͍͏ΑΓ΋ಡΈ΍͢͞ • %() ͷ ()

    ෦ʢσϦϛλʣ͸͍Ζ͍Ζͳ΋ͷʹஔ͖׵͑Մೳ • {} [] () <> # ͳͲͳͲ
  11. Safe navigation operator a.k.a. ΅ͬͪԋࢉࢠ (Ruby 2.3~) ref. Fe a

    ture #11537: Introduce "S a fe n a vig a tion oper a tor" - Ruby m a ster - Ruby Issue Tr a cking System ( https://bugs.ruby-l a ng.org/issues/ 11537 )
  12. val = foo&.bar&.baz bar = foo.nil? ? nil : foo.bar

    val = bar.nil? ? nil : bar.baz Safe navigation operator Ϩγʔό͕ nil ͷ৔߹ ɾҾ਺ͷධՁ͕ߦͳΘΕͳ͍ ɾϝιουݺͼग़͕͠ߦΘΕͳ͍ ɾnil Λฦ͢
  13. foo&.bar = val unless foo.nil? foo.bar = val end Safe

    navigation operator ୅ೖʹ΋ར༻Մೳ
  14. SymbolProc ref. Cl a ss: RuboCop::Cop::Style::SymbolProc — Document a tion

    for bb a tsov/RuboCop (m a ster) ( https://www.rubydoc.info/github/bb a tsov/ RuboCop/RuboCop/Cop/Style/SymbolProc ) ref. Ruby: Ξϯύαϯυͱίϩϯ`&:`ه๏ʹ͍ͭͯௐ΂ͯΈͨʛTechR a cho by BPSגࣜձࣾ https://techr a cho.bpsinc.jp/ h a chi8833/2021_05_27/66735
  15. ['a','b','c'].map(&:upcase) => ["A", "B", "C"] ['a','b','c'].map {|i| i.upcase} => ["A",

    "B", "C"] &:symbol & (Proc coercion) ͱ :symbol ͷ૊Έ߹Θͤ ʢ&: ͱ͍͏ԋࢉࢠͱ͍͏Θ͚Ͱ͸ͳ͍ʣ
  16. def foo(k1:, k2:, **kwrest) end # different from below #

    def foo(k1, k2, *rest) end ϨΞϦςΟɿ˒˒
  17. def foo(k1:, k2:, **kwrest) end foo(k1:'a', k2:'b', k3:'c', k4:'d') #

    kwrest => { k3:'c', k4:'d' } double splat parameter keyword Ҿ਺ͷʮ࢒Γશ෦ʯ *rest ͰҐஔҾ਺ͷʮ࢒Γશ෦ʯΛड͚Δͷͱ΄΅ಉ͡ def foo( a , b, *rest)
  18. Hash & Keyword Ҿ਺ͷʮলུʯ (Ruby 3.1~) ref. Ruby 3.1 ch

    a nges - Ruby Ch a nges ( https://rubyreferences.github.io/rubych a nges/3.1.html#v a lues-in-h a sh-liter a ls- a nd-keyword- a rguments-c a n-be-omitted )
  19. h = { x:, y: } # { x: x,

    y: y } と同じ foo(x:, y:) # (x: x, y: y) と同じ Hash & Keyword Ҿ਺ͷʮলུʯ key ͱಉ໊ͷม਺ࢀর͸লུԽ puts σόοά࣌ͳͲʹ΋ศར p x:, y:
  20. “Endless” method de fi nition (Ruby 3.0~) ref. Ruby 3.0

    ch a nges - Ruby Ch a nges ( https://rubyreferences.github.io/rubych a nges/3.0.html#endless-method-de f inition )
  21. [BASE_URL, path].join('/') .then { URI.open(it).read } .then { JSON.parse(it) }

    .dig('owner' ) .then { it.to_yaml } .then { File.write('out.yml', it) } ϨΞϦςΟɿ˒˒˒˒
  22. then ԋࢉࢠ (Ruby 2.6~) ref. Ruby 2.6 ch a nges

    - Ruby Ch a nges ( https://rubyreferences.github.io/rubych a nges/2.6.html#then- a s- a n- a li a s-for-yield_self )
  23. Ruby 2.4 Ҏલͷॻ͖ํ path = [BASE_URL, path].join('/') json = URI.open(path).read

    content = JSON.parse(json) owner = content.dig('owner') yaml = owner.to_yaml File.write('out.yml', yaml)
  24. #yield_self (Ruby 2.5~) [BASE_URL, path].join('/') .yield_self {|path| URI.open(path).read } .yield_self

    {|json| JSON.parse(json) } .dig('owner') .yield_self {|owner| owner.to_yaml } .yield_self {|yaml| File.write('out.yml',yaml) } ࣗ਎ΛҾ਺ʹϒϩοΫΛ࣮ߦ & ϒϩοΫͷ݁ՌΛฦ͢
  25. #yield_self ͷผ໊ #then [BASE_URL, path].join('/') .then {|path| URI.open(path).read } .then

    {|json| JSON.parse(json) } .dig('owner') .then {|owner| owner.to_yaml } .then {|yaml| File.write('out.yml',yaml) } #tap ͱ͍͏ྨࣅϝιου΋͋Δ ʢࣗ਎ΛҾ਺ʹϒϩοΫΛ࣮ߦ & ࣗ਎Λฦ͢ʣ
  26. it ͱͷ૊Έ߹Θͤ [BASE_URL, path].join('/') .then { URI.open(it).read } .then {

    JSON.parse(it) } .dig('owner' ) .then { it.to_yaml } .then { File.write('out.yml', it) }
  27. Anonymous block argument (Ruby 3.1~) & Anonymous arguments passing (Ruby

    3.2~) ref. Ruby 3.1 ch a nges - Ruby Ch a nges ( https://rubyreferences.github.io/rubych a nges/3.1.html# a nonymous-block- a rgument ) ref. Ruby 3.2 ch a nges - Ruby Ch a nges ( https://rubyreferences.github.io/rubych a nges/3.2.html# a nonymous- a rguments-p a ssing- improvements )
  28. def wrap_f1(&) = f1(&) # ブロック引数 def wrap_f2(*) = f2(*)

    # 全位置引数 def wrap_f3(**) = f3(**) # 全キーワード引数 def wrap_f4(*, **) f4_1(*) f4_2(**) end # こういった書き方も出来る શҾ਺Λͦͷ··ผͷϝιου΁
  29. if user in { name:, role: } puts %(#{name} is

    #{role}) end ϨΞϦςΟɿ˒˒˒˒˒˒
  30. Pattern matching (in) (Ruby 2.7~) ref. Ruby 2.7 ch a

    nges - Ruby Ch a nges ( https://rubyreferences.github.io/rubych a nges/2.7.html#p a ttern-m a tching ) ref. p a ttern_m a tching - Document a tion for Ruby 3.5 ( https://docs.ruby-l a ng.org/en/m a ster/synt a x/p a ttern_m a tching_rdoc.html )
  31. ύλʔϯϚονϯά • P a ttern m a tching is a

    fe a ture a llowing deep m a tching of structured v a lues: checking the structure a nd binding the m a tched p a rts to loc a l v a ri a bles. • ύλʔϯϚονϯά͸ωετΛؚΉσʔλߏ଄ͷϚονϯάΛՄೳʹ ͢Δػೳ • σʔλߏ଄Λ֬ೝ͢Δ (checking) • Ұகͨ͠෦෼ΛϩʔΧϧม਺ʹׂΓ౰ͯΔ (binding)
  32. if user in { name:, role: } puts %(#{name} is

    #{role}) end Pattern matching (in) in ۟ͷޙʹ Hash Λهड़͢Δ͜ͱͰ ߏ଄ͷνΣοΫͱม਺΁ͷ୅ೖΛಉ࣌ʹߦ͍ͬͯΔ ͜͜Ͱ {name:, role:} ͸লུه๏ {name:n, role:r} ͱॻ͍ͨ৔߹͸ม਺ n,r ͕ఆٛ͞ΕΔ
  33. Pattern matching (=>) (Ruby 3.0~) ref. Ruby 3.0 ch a

    nges - Ruby Ch a nges ( https://rubyreferences.github.io/rubych a nges/3.0.html#p a ttern-m a tching ) ref. p a ttern_m a tching - Document a tion for Ruby 3.5 ( https://docs.ruby-l a ng.org/en/m a ster/synt a x/p a ttern_m a tching_rdoc.html )
  34. user => { name:, role: } puts %(#{name} is #{role})

    Pattern matching (=>) => ӈ୅ೖ(rightw a rd a ssignment) ߏจ ߏ଄Ϛον͠ͳ͍৔߹͸Τϥʔ͕ rise ͞ΕΔ (NoMatchingPatternKeyError ͳͲ)
  35. File.read('test.txt') .split("\n") .map(&:strip) .reject(&:empty?) .first(10) => lines [BASE_URL, path].join('/') .then

    { URI.open(it).read } .then { JSON.parse(it) } .dig('owner' ) .then { it.to_yaml } => yaml => Λ୅ೖ͚ͩͷ༻్Ͱ࢖͏͜ͱ΋ ͜Ε͸࠷ۙ ݟΔؾ͕͢Δ ϨΞϦςΟ௿Ί … ͔΋
  36. Pattern matching (Expression) (Ruby 3.1~) ref. Ruby 3.1 ch a

    nges - Ruby Ch a nges ( https://rubyreferences.github.io/rubych a nges/3.1.html#p a ttern-m a tching ) ref. p a ttern_m a tching - Document a tion for Ruby 3.5 ( https://docs.ruby-l a ng.org/en/m a ster/synt a x/p a ttern_m a tching_rdoc.html )
  37. user => { name:, age: 13..28} puts %(#{name} is gen-Z)

    Pattern Matching(Expressions) ࣜΛ࢖ͬͨύλʔϯϚον ϩʔΧϧม਺Ҏ֎ͷม਺(non-loc a l v a ri a bles) Λࣜ෦ʹ࢖͏৔߹͸ ^ ۟Λ࢖ͬͨ pinning ॲཧ͕ඞཁ (ৄࡉུ) ม਺΁ͷׂΓ౰ͯ͸ߦΘΕͳ͍
  38. case user in role: "admin" puts "super user" in age:

    13..28 puts %(#{name} is gen-Z) in name:, role: puts %(#{name} is #{role}) end ϨΞϦςΟɿ˒˒˒˒˒˒˒
  39. Pattern matching (case) (Ruby 3.2~) ref. Ruby 3.2 ch a

    nges - Ruby Ch a nges ( https://rubyreferences.github.io/rubych a nges/3.2.html#p a ttern-m a tching ) ref. p a ttern_m a tching - Document a tion for Ruby 3.5 ( https://docs.ruby-l a ng.org/en/m a ster/synt a x/p a ttern_m a tching_rdoc.html )
  40. case user in role: "admin" puts "super user" in age:

    13..28 puts %(#{name} is gen-Z) in name:, role: puts %(#{name} is #{role}) end Pattern matching (case) case-when ߏจͱ΄΅ಉ͡
  41. • Ruby: "uselessγϯλοΫεγϡΨʔ"γϦʔζʮύλʔϯϚονϯά ʢ1/3ʣʯʢ຋༁ʣʛTechR a cho by BPSגࣜձࣾ • https://techr

    a cho.bpsinc.jp/h a chi8833/2024_01_31/138590 • ·ͩ·ͩԞਂ͍ • ΫϥεͷҰகνΣοΫͱ͔ • "Find p a ttern" value in [*, pattern, *] ͱ͔ Pattern matching ਂ۷Γ
  42. fl ip- fl op ৚݅ࣜ ref. ԋࢉࢠࣜ (Ruby 3.4 ϦϑΝϨϯεϚχϡΞϧ)

    ( https://docs.ruby-l a ng.org/j a /l a test/doc/spec=2foper a tor.html#r a nge_cond )
  43. 5.times{|n| p n if (n==2)..(n==3) } # => 2 #

    3 fl ip- fl op ৚݅ࣜ ʮ৚݅ࣜͱͯ͠ʯൣғࣜΛهड़ͨ͠ͱ͖͚ͩͷಛघಈ࡞ "ࠨ෦Λຬͨͨ͠Βɺӈ෦Λຬͨ͢·Ͱ true" "Range ͷதʹऩ·ͬͯͨΒ" Ͱ͸ͳ͍
  44. [1,2,3,4,5,4,3,2,1].each{|n| p n if (n==3..) } # => 3 #

    4 # 5 # 4 # 3 # 2 ← でる # 1 ← でる fl ip- fl op తͳಈ࡞ྫ
  45. • ʮঢ়ଶʯΛ࣋ͭಛघͳ৚݅ࣜ • ঢ়ଶ = ॳظঢ়ଶ or ࣜ1͕Ϛονͨ͠ޙ or ࣜ2͕Ϛονͨ͠ޙ

    • .. ͷ৔߹ͱ ... ͷ৔߹Ͱಈ࡞͕एׯҟͳΔ • sed ΍ a wk ༝དྷͷಈ࡞ • ݸਓతʹ͸ɺ࣮ࡍʹ࢖ΘΕ͍ͯΔͱ͜ΖΛݟͨ͜ͱ͕ͳ͍ • ύʔαʔͱ͔Ͱ͔ͭΘΕ͍ͯΔΜͩΖ͏ɺͱࢥ͏ • ಈ࡞Λޡղ͠΍͍ͨ͢Ί͚͞ΒΕ͍ͯΔɺͷ͔΋ fl ip- fl op ਂ۷Γ