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

[RubyKaigi 2024] Ruby Mixology 101: adding sho...

[RubyKaigi 2024] Ruby Mixology 101: adding shots of PHP, Elixir, and more

https://rubykaigi.org/2024/presentations/palkan_tula.html

How often have you heard, “I wish Ruby had X from Y”? Developers tend to desire features they love in one language to be available in another. That’s why, for example, we got pattern matching and shorthand Hashes added to Ruby. What’s next? What will inspire the next Ruby syntax addition? Crystal? Elixir? Zig (have you heard about it)? PHP (why not)?

Let’s embark on a fantastic journey of exploring syntax features from other languages, such as method overloading or null coalescing assignment, and how to port them to Ruby. But why is it fantastic? I want to turn fantasy into reality and show how we can experiment with Ruby syntax additions without waiting for official releases with experimental features.

Vladimir Dementyev

May 17, 2024
Tweet

More Decks by Vladimir Dementyev

Other Decks in Programming

Transcript

  1. 3

  2. 4

  3. palkan_tula palkan h = {x:, y:} def foo(&) bar(&) 5

    2015 2018 2019 2020 2021 2022 2024 1... &. ...1 case ... in def x = 1 def foo(*) bar(*) 1 in x proc { it } def foo(...) proc { _1 }
  4. palkan_tula palkan –D. Crystal “The only languages which do not

    change are dead ones” 7 มΘΒͳ͍ݴޠ͸ࢮΜͩݴޠͰ͢ɻ
  5. palkan_tula palkan 15 2013 2015 2017 2019 2020 2021 &.

    proc { it } 2024 proc { it } &. h = {x:, y:} case ... in case ... in h = {x:, y:} def x = 1 def x = 1
  6. palkan_tula palkan I. Encourage early adopters to experiment with proposals.

    18 ΞʔϦʔΞμϓλʔʹ৽نఏҊͰ࣮ݧͯ͠΋Β͏
  7. 20

  8. 21

  9. 23

  10. 24

  11. 25

  12. palkan_tula palkan I. Encourage early adopters to experiment with proposals.

    32 ΞʔϦʔΞμϓλʔʹ৽نఏҊͰ࣮ݧͯ͠΋Β͏
  13. palkan_tula palkan I. Encourage early adopters to experiment with proposals.

    II. Learn from other languages. 32 ΞʔϦʔΞμϓλʔʹ৽نఏҊͰ࣮ݧͯ͠΋Β͏ ଞͷݴޠΛࢀߟʹ͢Δ
  14. 35

  15. 2

  16. palkan_tula palkan user["name"] = user["name"] ?: "Guest" 36 PHP: $user['name']

    ??= 'Guest' Kotlin: JavaScript: user.name ??= 'guest' Elvis operator
  17. palkan_tula palkan $ 40 ruby -e 'a ?= 1' -e:1:

    syntax error, unexpected integer literal, expecting end-of-input a ?= 1 -e: compile error (SyntaxError)
  18. palkan_tula palkan ?= a = nil a ?= false #

    a is false a ?= 1 # a is false a ||= 1 # a is 1 41
  19. 42

  20. 46

  21. palkan_tula palkan ?= ❤ Hash h = {val: nil} #

    h[:val] = 42 unless h.key?(:val) h[:val] ?= 42 h #=> {val: nil} 47
  22. palkan_tula palkan ?= ❤ @var def current_user return @current_user if

    defined?(@current_user) @current_user = find_user end 48
  23. palkan_tula palkan def current_user @current_user ?= find_user end 49 def

    current_user return @current_user if defined?(@current_user) @current_user = find_user end ?= ❤ @var
  24. 50

  25. palkan_tula palkan def current_user @current_user ?= find_user end 51 def

    current_user return @current_user if defined?(@current_user) @current_user = find_user end ?= ❤ @var
  26. palkan_tula palkan ΦϒδΣΫτγΣΠϓ def current_user @current_user ?= find_user end 51

    def current_user return @current_user if defined?(@current_user) @current_user = find_user end $ Object shapes :( ?= ❤ @var
  27. 52

  28. palkan_tula palkan I. (a = false) ?= 2024 #=> false

    II. h[:x] ?= 5 53 Use cases Ϣʔεέʔε
  29. palkan_tula palkan I. (a = false) ?= 2024 #=> false

    II. h[:x] ?= 5 III. @value ?= maybe_some 53 Use cases Ϣʔεέʔε
  30. palkan_tula palkan εϚʔτΦϒδΣΫτγΣΠϓ I. (a = false) ?= 2024 #=>

    false II. h[:x] ?= 5 III. @value ?= maybe_some ⏳ Smart object shapes 54 Use cases Ϣʔεέʔε
  31. 57

  32. palkan_tula palkan def beach(*temperature) case temperature in :celcius | :c,

    (20..45) :favorable in :kelvin | :k, (293..318) :scientifically_favorable in :fahrenheit | :f, (68..113) :favorable_in_us else :avoid_beach end end 58
  33. palkan_tula palkan beach(Temperature) -> case Temperature of {celsius, N} when

    N >= 20, N =< 45 -> 'favorable'; {kelvin, N} when N >= 293, N =< 318 -> 'scientifically favorable'; {fahrenheit, N} when N >= 68, N =< 113 -> 'favorable in the US'; _ -> 'avoid beach' end. 59
  34. palkan_tula palkan beach({celsius, N}) when N >= 20, N =<

    45 -> 'favorable'; beach({kelvin, N}) when N >= 293, N =< 318 -> 'scientifically favorable'; beach({fahrenheit, N}) when N >= 68, N =< 113 -> 'favorable in the US'; beach(_) -> 'avoid beach'. 60
  35. palkan_tula palkan def beach(*temperature) case temperature in :celcius | :c,

    (20..45) :favorable in :kelvin | :k, (293..318) :scientifically_favorable in :fahrenheit | :f, (68..113) :favorable_in_us else :avoid_beach end end 63
  36. palkan_tula palkan def beach in :celcius | :c, (20..45) :favorable

    end def beach in :kelvin | :k, (293..318) :scientifically_favorable end def beach in :fahrenheit | :f, (68..113) :favorable_in_us end def beach(...) = :avoid_beach 64
  37. palkan_tula palkan $ 65 ruby -e 'def foo in :c,

    Integer => v; v; end' -e:1: syntax error, unexpected `in', expecting ';' or '\n' def foo in :c, Integer => v; v; end -e: compile error (SyntaxError)
  38. palkan_tula palkan def ... in No new keywords Resembles other

    languages (Elixir, Crystal, etc.) Idiomatic Ruby & 66 ৽͍͠ΩʔϫʔυΛ૿΍͞ͳ͍ ଞͷݴޠʹࣅͤΔ Ruby ͷΠσΟΦϜʹै͏
  39. 67

  40. 69

  41. palkan_tula palkan foo(*args) — ' foo(**kwargs) — ' foo(*args, **kwargs)

    — ( def foo in <ptrn> (if | unless) <expr> — ( 70
  42. palkan_tula palkan foo(*args) — ' foo(**kwargs) — ' foo(*args, **kwargs)

    — ( def foo in <ptrn> (if | unless) <expr> — ( prepend/class_eval/etc. — ' 70
  43. 71

  44. palkan_tula palkan 73 beach(Temperature) -> case Temperature of {celsius, N}

    when N >= 20, N =< 45 -> 'favorable'; {kelvin, N} when N >= 293, N =< 318 -> 'scientifically favorable'; {fahrenheit, N} when N >= 68, N =< 113 -> 'favorable in the US'; _ -> 'avoid beach' end. beach({celsius, N}) when N >= 20, N =< 45 -> 'favorable'; beach({kelvin, N}) when N >= 293, N =< 318 -> 'scientifically favorable'; beach({fahrenheit, N}) when N >= 68, N =< 113 -> 'favorable in the US'; beach(_) -> 'avoid beach'.
  45. palkan_tula palkan ಉ͡όΠτίʔυ Same byte code 74 beach(Temperature) -> case

    Temperature of {celsius, N} when N >= 20, N =< 45 -> 'favorable'; {kelvin, N} when N >= 293, N =< 318 -> 'scientifically favorable'; {fahrenheit, N} when N >= 68, N =< 113 -> 'favorable in the US'; _ -> 'avoid beach' end. beach({celsius, N}) when N >= 20, N =< 45 -> 'favorable'; beach({kelvin, N}) when N >= 293, N =< 318 -> 'scientifically favorable'; beach({fahrenheit, N}) when N >= 68, N =< 113 -> 'favorable in the US'; beach(_) -> 'avoid beach'.
  46. 75

  47. palkan_tula palkan CoffeeScript: define_method(:initialize) {|@a, @b|} 79 def initialize(@a, @b)

    initialize(@a, @b) -> def initialize(@name : String) Crystal: Ruby <1.9:
  48. 80

  49. 81

  50. 82

  51. 83

  52. palkan_tula palkan ෆม Zig: 87 var pt: Point = .{

    .x = 3, .y = 4, }; #{ x: 3, y: 4 } JavaScript (proposal): Anonymous Struct Immutable
  53. 89

  54. palkan_tula palkan "https://api.github.com/repos/ruby/ruby" .then { URI.parse(it) } .then { Net::HTTP.get(it)

    } .then { JSON.parse(it).fetch("stargazers_count") } .then { "Ruby has #{it} stars" } .then { Kernel.puts(it) } 94
  55. palkan_tula palkan Try using proposed syntax in your code Share

    you examples Report confusions and edge cases 96 ͜ͷจ๏Λࣗ෼ͷίʔυͰࢼͯ͠ΈΔ ॻ͍ͨίʔυΛڞ༗͢Δ ͏·͍͔͘ͳ͍ྫ΍ΤοδέʔεΛใࠂ
  56. 97