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 記法を皮切りに、いくつかのちょっと珍しい「書き方」をご紹介する。

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 ਂ۷Γ