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

Ruby 3.0 Redux (Spark Academy, Jan 2021)

Ruby 3.0 Redux (Spark Academy, Jan 2021)

1be785d1d788b82929e55fc83a9f0aaa?s=128

Bozhidar Batsov

January 28, 2021
Tweet

Transcript

  1. HEY, THERE!

  2. ABOUT ME  Bozhidar (Божидар) a.k.a. Bug  Lives in

    Sofia, Bulgaria  Works at Toptal (https://toptal.com)  Devoted to Emacs  Author/maintainer of many Emacs and Clojure libraries and tools (e.g. Projectile, CIDER, nREPL, Orchard)  Author of RuboCop, editor of the community Ruby Style Guide (https://rubystyle.guide), blah, blah, blah  @bbatsov  @bozhidarb on Reddit (long story)  metaredux.com  emacsredux.com
  3. POLAND AND ME  Krakow  Oswiecim  Gdansk 

    Gdinya  Sopot  Malbork  Warsaw  Wroclaw  Poznan
  4. 2020

  5. NO RUBY CONFERENCES SINCE 2019

  6. THAT MAKES ME VERY SAD

  7. None
  8. WEDDING

  9. I’VE BUILT A DESKTOP PC AND SWITCHED (BACK) TO LINUX

  10. None
  11. None
  12. OH, WELL… HELLO, WINDOWS!

  13. THIS PRESENTATION WAS CREATED IN POWERPOINT!

  14. I LOVE WINDOWS!

  15. GAMING ACHIEVEMENTS  StarCraft 2  Diablo 3  Tomb

    Raider  Counter-Strike: Global Offensive
  16. NETFLIX ACHIEVEMENTS  Cobra Kai  The Queen’s Gambit 

    Love and Anarchy  Sex Education  The Crown  Titans
  17. RUBOCOP 1.0

  18. GREAT SUCCESS

  19. LOCAL TOURISM

  20. None
  21. None
  22. None
  23. None
  24. None
  25. None
  26. None
  27. None
  28. None
  29. None
  30. None
  31. None
  32. None
  33. None
  34. WHAT ABOUT RUBY 3?

  35. RUBY 3.0 REDUX BOZHIDAR BATSOV

  36. RICH HICKEY, CREATOR OF CLOJURE

  37. DICTIONARY DEFINITIONS

  38. RUBY NOUN 1. A PRECIOUS STONE CONSISTING OF CORUNDUM IN

    COLOUR VARIETIES VARYING FROM DEEP CRIMSON OR PURPLE TO PALE ROSE. 2. A PROGRAMMING LANGUAGE OPTIMISED FOR PROGRAMMER HAPPINESS
  39. 3 (THREE) NUMBER 1. EQUIVALENT TO THE SUM OF ONE

    AND TWO; ONE MORE THAN TWO; 3 2. A MYSTICAL VERSION RARELY ACHIEVED BY MOST SOFTWARE PROJECTS.
  40. REDUX ADJECTIVE 1. BROUGHT BACK, REVIVED EMACS ERA REDUX 2.

    (USUALLY POSTPOSITIVE) (ESP OF AN ARTISTIC WORK) PRESENTED IN A NEW WAY APOCALYPSE NOW REDUX
  41. RUBY 3.0, THE SHORT (BORING) VERSION  Released on Christmas

    2020  The first major Ruby release since Ruby 2.0 (released way back in 2013)  Official release notes (https://www.ruby-lang.org/en/news/2020/12/25/ruby-3-0-0-released/)  Detailed release notes (https://rubyreferences.github.io/rubychanges/3.0.html)
  42. THE LONG (EXCITING) STORY

  43. THE LONG VERSION  The programming landscape has changed a

    lot in the past 10 years  Rails is no longer hip  Ruby is facing some fierce competition from newer languages like Clojure, Elixir, Go, Java, etc  Ruby 3 has the ambitious goal to save Ruby’s future  Matz has been talking about Ruby 3 since 2015  He had a keynote about Ruby 3 at EuRuKo 2016 in Sofia  A lot of ideas for Ruby 3 have floated around since then
  44. MAIN THEMES

  45. PERFORMANCE

  46. IMPROVED PROGRAMMING SAFETY

  47. BETTER TOOLS (FOR RUBY PROGRAMMERS)

  48. REMOVAL OF SOME CRUFT (LEGACY/OBSOLETE FUNCTIONALITY)

  49. LANGUAGE STABILITY

  50. REIGNITE THE RUBY COMMUNITY

  51. VICTIM OF THE HYPE CYCLE

  52. None
  53. „There has been, for instance, a consistent migratory pattern from

    Ruby to node.js to Go, Rust, and Elixir. At first, each community is defined by its potential. But as that potential is realized, the community begins to be defined by its compromises. That change is felt most keenly by the people who were there first, who remember what it was like when anything seemed possible. They feel fenced in and so they move on, in search of their golden city.“ -- Zack Telman
  54. “We have to feed the community intellectually.” -- Matz

  55. “We have to keep moving forward.” -- Matz

  56. SMALL LANGUAGE CHANGES

  57. ENDLESS RANGES (RUBY 2.6)

  58. case year when(2030..) :mysterious_future when(2020..) :twenties when(2010..) :nowish else :ancient_past

    end [1, 2, 3].zip(1..) { |a, index| puts "#{a}, #{index}"} # 1 1 # 2 2 # 3 3
  59. BEGINLESS RANGES (RUBY 2.7)

  60. arr = (1..10).to_a # Select first 6 elements arr[..5] #

    => [1, 2, 3, 4, 5, 6] # Select first 5 elements > arr[...5] # => [1, 2, 3, 4, 5] # grep (INFINITY..5) in (1..5) (1..10).grep(..5) # => [1, 2, 3, 4, 5]
  61. case temperature when ..-15 puts "Deep Freeze" when -15..8 puts

    "Refrigerator" when 8..15 puts "Cold" when 15..25 puts "Room Temperature" when (25..) # notice the brackets here puts "Hot" end
  62. # In Rails User.where(created_at: (..DateTime.now))

  63. None
  64. FLIP-FLOPS WERE DEPRECATED IN RUBY 2.6…

  65. AND REINSTATED IN RUBY 2.7

  66. None
  67. SAFE NAVIGATION OPERATOR (RUBY 2.3)

  68. # Regular Ruby (before Ruby 2.3) if account && account.owner

    && account.owner.address do_something(account) end # Rails (ActionSupport) if account.try(:owner).try(:address) do_something(account) end # Safe Navigation Operator account&.owner&.address
  69. # Original Version account?.owner?.address predicate??.foo

  70. None
  71. NUMBERED PARAMETERS

  72. # Original Proposal numbers.map { Math.log2(@1) } foo.bar { @1

    + @2 } # Final Version numbers.map { Math.log2(_1) } foo.bar { _1 + _2 }
  73. h = Hash.new { _1[_2] = "Go Fish: #{_2}" }

  74. PIPELINE OPERATOR

  75. foo() .bar(1, 2) .display # Pipeline Operator (removed after receiving

    # negative feedback from the community) foo() |> bar 1, 2 |> display
  76. None
  77. LACK OF FOCUS

  78. PATTERN MATCHING # before def display_name(name_hash) if name_hash[:username] name_hash[:username] elsif

    name_hash[:nickname] && name_hash[:realname] && name_hash[:realname][:first] && name_hash[:realname][:last] "#{name_hash[:nickname]} #{name_hash[:realname][:first]} #{name_hash[:realname][:last]}" elsif name_hash[:first] && name_hash[:last] "#{name_hash[:first]} #{name_hash[:last]}" else 'New User' end end # after def display_name(name_hash) case name_hash in {username: username} username in {nickname: nickname, realname: {first: first, last: last}} "#{nickname} #{first} #{last}" in {first: first, last: last} "#{first} #{last}" else 'New User' end end
  79. RUBY 3 AS AN IDEA

  80. None
  81. MAKE RUBY COOL AGAIN

  82. WE’VE BEEN MAKING PROGRESS TOWARDS RUBY 3 IN EVERY RECENT

    RUBY RELEASE
  83. RUBY 3 IS GOING TO BE 3 TIMES FASTER THAN

    RUBY 2.0
  84. RUBY 3 IS GOING TO BE 3 TIMES FASTER THAN

    RUBY 2.0
  85. THE ROAD TO RUBY 3X3  Generational GC (Ruby 2.1)

     Incremental GC (Ruby 2.2)  MJIT (Ruby 2.6)
  86. BETTER RUBY TOOLS  New AST library (Ruby 2.6) 

    The bundling of Bundler (Ruby 2.6)  Gemifying the Standard Library (ongoing process)  See https://stdgems.org/ for details  Improvements to IRB  syntax highlighting  debugging capabilities  Multi-line editing  Performance improvements  Improvements to RDoc
  87. RUBY 3.0

  88. SEPARATION OF KEYWORD AND OPTIONAL PARAMETERS (BREAKING CHANGE)

  89. RUBY 2.X If the last argument of a method call

    is a Hash, Ruby < 2.7 will automatically convert to keyword arguments. # Those are more or less the same in Ruby 2.x def foo(name, options = {}) end def bar(name, **options) End foo('Bruce Wayne', age: 10) bar('Bruce Wayne’, { age: 10 })
  90. RUBY 3.X The abovementioned automatic conversion will stop. Ruby 2.7

    emits a warning, which is an error in Ruby 3. # Those are different in Ruby 3.x def foo(name, options = {}) end def bar(name, **options) End # Works, because you’re still passing a hash foo('Bruce Wayne', age: 10) # Doesn’t work anymore bar('Bruce Wayne’, { age: 10 }) # Magic fix bar('Bruce Wayne’, **{ age: 10 })
  91. # Those are more or less the same in Ruby

    2.x def foo(name, options = {}) end def bar(name, **options) end # Let's pass a hash parameter foo('Bruce Wayne', {age: 10}) # Ruby 2.6: works # Ruby 2.7: warns: Using the last argument as keyword parameters is deprecated; maybe ** should be added to th e call # Ruby 3.0: ArgumentError (wrong number of arguments (given 2, expected 1)) bar('Bruce Wayne', age: 10) # => works h = {age: 10} bar('Bruce Wayne', **h) # => works, ** is mandatory # The last hash argument still allowed to be passed without {}: foo('Bruce Wayne', age: 10) # => works
  92. THE FAST AND THE FURIOUS

  93. When I first declared “Ruby3x3” in the conference keynote, many

    including members of the core team felt “Matz is a boaster”. In fact, I felt so too. But we did. I am honored to see the core team actually accomplished to make Ruby 3.0 three times faster than Ruby 2.0 (in some benchmarks). – Matz
  94. None
  95. None
  96. As of Ruby 3.0, JIT is supposed to give performance

    improvements in limited workloads, such as games (Optcarrot), AI (Rubykon), or whatever application that spends majority of time in calling a few methods many times. Although Ruby 3.0 significantly decreased a size of JIT-ed code, it is still not ready for optimizing workloads like Rails, which often spend time on so many methods and therefore suffer from i-cache misses exacerbated by JIT. Stay tuned for Ruby 3.1 for further improvements on this issue.
  97. None
  98. ENDLESS METHODS

  99. # good def the_answer = 42 def get_x = @x

    def square(x) = x * x # Not (so) good: has side effect def set_x(x) = (@x = x) def print_foo = puts("foo") # bad def fib(x) = if x < 2 x else fib(x - 1) + fib(x - 2) end
  100. FUN (AND USEFUL) TRIVIA  Started as April’s Fool joke

     Matz liked the idea and it became a real feature  Endless definitions should ideally:  Be single-line  Be free of side-effects
  101. STATIC TYPING

  102. HTTPS://BUGS.RUBY-LANG.ORG/ISSUES/9999

  103. 2010s were an age of statically typed programming languages. Ruby

    seeks the future with static type checking, without type declaration, using abstract interpretation. RBS & TypeProf are the first step to the future. More steps to come. — Matz
  104. RBS # sig/merchant.rbs class Merchant attr_reader token: String attr_reader name:

    String attr_reader employees: Array[Employee] def initialize: (token: String, name: String) -> void def each_employee: () { (Employee) -> void } -> void | () -> Enumerator[Employee, void] end
  105. DUCK TYPING interface _Appendable # Requires `<<` operator which accepts

    `String` object. def <<: (String) -> void end # Passing `Array[String]` or `IO` works. # Passing `TrueClass` or `Integer` doesn't work. def append: (_Appendable) -> String
  106. UNION TYPES & METHOD OVERLOADING class Comment # A comment

    can be made by a User or a Bot def author: () -> (User | Bot) # Two overloads with/without blocks def each_reply: () -> Enumerator[Comment, void] | { (Comment) -> void } -> void ... end
  107. THE BENEFITS OF STATIC TYPING  Better tools (IDEs, linters,

    etc)  Safer code  Easier maintenance
  108. TOOLS  Sorbet (static type checker)  RBI vs RBS

     Steep (static type checker)  TypeProf
  109. SORBET IN ACTION

  110. TYPEPROF IN ACTION # test.rb def foo(x) if x >

    10 x.to_s else nil end end foo(42) # $ typeprof test.rb # Classes class Object def foo : (Integer) -> String? end
  111. RUBY ACTORS (RACTORS)

  112. THE ARTIST FORMERLY KNOWN AS GUILDS

  113. I REGRET ADDING THREADS TO RUBY. - MATZ

  114. It’s multi-core age today. Concurrency is very important. With Ractor,

    along with Async Fiber, Ruby will be a real concurrent language. – Matz
  115. None
  116. None
  117. ractor1, ractor2 = *(1..2).map do Ractor.new do number = Ractor.recv

    Math.sqrt(number) end end # send parameters ractor1.send 3**71 ractor2.send 4**51 p ractor1.take #=> 8.665717809264115e+16 p ractor2.take #=> 2.251799813685248e+15
  118. RANDOM CHANGES

  119. MISC CHANGES  $SAFE and $KCODE lost their special meaning

     Assignment to numbered parameters (e.g. _1) will now result in a syntax error (it’s a warning in Ruby 2.7)  yield in a singleton class definitions, which was deprecated in 2.7, will now result in a syntax error  Another batch of IRB improvements  Continued efforts to gemify the Ruby standard library (https://stdgems.org/)
  120. None
  121. Ruby 3.0 is a (major) milestone. The language is evolved,

    keeping compatibility. But it’s not the end. Ruby will keep progressing, and become even greater. Stay tuned! — Matz
  122. RUBY 3.1  MJIT improvements that might benefit Rails 

    Ractor-based JIT worker  On-Stack Replacement  Reduce the size of JIT-ed code
  123. MATZ PLANS TO RETIRE IN 2025

  124. None
  125. RUBY 4

  126. RUBY 4X4

  127. RUBY 4 IS GOING TO BE 4 TIMES FASTER THAN

    RUBY 3
  128. RUBY 4 IS GOING TO BE 12 TIMES FASTER THAN

    RUBY 2
  129. RUBY 4 IS FINALLY GOING TO BE FAST ENOUGH!

  130. None
  131. RUBOCOP NOW SUPPORTS RUBY 3  Support was introduced in

    RuboCop 1.7  The bulk of the work so far was related to endless method definitions  The support for Ruby 3.0 will mature and evolve over the course of the next few months
  132. RUBOCOP 1.9 IS OUT TODAY!

  133. THE END

  134. RESOURCES  https://www.ruby-lang.org/en/news/2020/12/25/ruby-3-0-0-released/  https://rubyreferences.github.io/rubychanges/3.0.html  https://www.fastruby.io/blog/rails/ruby/performance/how-fast-is-ruby-3-on-rails.html  https://codefol.io/posts/is-ruby-3-actually-three-times-faster/ 

    https://medium.com/@k0kubun/ruby-3-0-jit-and-beyond-4d9404ce33c  https://juanitofatas.com/ruby-3-keyword-arguments  https://developer.squareup.com/blog/the-state-of-ruby-3-typing/