What If...?: Ruby 3

What If...?: Ruby 3

Slides for my RubyConf talk on the possible futures of Ruby.

Facce030b679bda34eb7c64885a741fc?s=128

Eric Weinstein

November 15, 2017
Tweet

Transcript

  1. What If...?: Ruby 3 # Eric Weinstein # RubyConf 2017

    # New Orleans, LA, USA # 15 November 2017
  2. The Future of Ruby Part III: The Future(s)

  3. None
  4. Part 0: Hello!

  5. About Me eric_weinstein = { employer: 'Fox Networks Group', github:

    'ericqweinstein', twitter: 'ericqweinstein', website: 'ericweinste.in' } 30% off with RUBYCONF30! ->
  6. Agenda • What If...? comics • The power of stories

    • Slide vs. speech • Three stories
  7. What If...?

  8. None
  9. Ruby 3x3 • Goal: Ruby 3 will be 3x faster

    than Ruby 2 • I think we’ll get there! But what else will we get? • Three "What if...?" scenarios: types, environment, concurrency
  10. (It wasn’t.)

  11. None
  12. Part 1: What if Ruby Had a Static Type System?

  13. Static vs. Dynamic • Static: variable types (e.g. Fixnum, String,

    Symbol) are known at compile time • May or may not make use of type inference • Dynamic: variable types are not known until runtime
  14. Weak vs. Strong • Don’t @ me • Weak: implicit

    type conversion • Strong: no implicit type conversion • Ruby is strongly, dynamically typed
  15. (It encourages him.)

  16. Weak vs. Strong • Don’t @ me • Weak: implicit

    type conversion • Strong: no implicit type conversion • Ruby is strongly, dynamically typed
  17. YARV Tokenize -> lex -> parse -> compile to bytecode

    -> execute!
  18. 10.times do |n| puts n end [[[1, 0], :on_int, "10"],

    [[1, 2], :on_period, "."], [[1, 3], :on_ident, "times"], [[1, 8], :on_sp, " "], [[1, 9], :on_kw, "do"], [[1, 11], :on_sp, " "], [[1, 12], :on_op, "|"], [[1, 13], :on_ident, "n"], [[1, 14], :on_op, "|"], [[1, 15], :on_ignored_nl, "\n"], [[2, 0], :on_sp, " "], [[2, 2], :on_ident, "puts"], [[2, 6], :on_sp, " "], [[2, 7], :on_ident, "n"], [[2, 8], :on_nl, "\n"], [[3, 0], :on_kw, "end"], [[3, 3], :on_nl, "\n"]] Credit: Ruby Under a Microscope, Pat Shaughnessy
  19. Parsing • LALR Algorithm • $ ruby -y example.rb Credit:

    Ruby Under a Microscope, Pat Shaughnessy
  20. YARV Bytecode RubyVM::InstructionSequence.compile(code).disasm

  21. == disasm: #<ISeq:<compiled>@<compiled>>================================ == catch table | catch type: break

    st: 0002 ed: 0008 sp: 0000 cont: 0008 |------------------------------------------------------------------------ 0000 trace 1 ( 1) 0002 putobject 10 0004 send <callinfo!mid:times, argc:0>, <callcache>, block in <compiled> 0008 leave == disasm: #<ISeq:block in <compiled>@<compiled>>======================= == catch table | catch type: redo st: 0002 ed: 0010 sp: 0000 cont: 0002 | catch type: next st: 0002 ed: 0010 sp: 0000 cont: 0010 |------------------------------------------------------------------------ local table (size: 2, argc: 1 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1]) [ 2] n<Arg> 0000 trace 256 ( 1) 0002 trace 1 ( 2) 0004 putself 0005 getlocal_OP__WC__0 2 0007 opt_send_without_block <callinfo!mid:puts, argc:1, FCALL|ARGS_SIMPLE>, <callcache> 0010 trace 512 ( 3) 0012 leave ( 2)
  22. None
  23. ($ brew uninstall ruby && brew install crystal)

  24. class Account def initialize @balance = 0 end def balance

    @balance end def deposit(amount) @balance += amount end def withdraw(amount) @balance -= amount end end
  25. Dependent Types *example> getTransactions [4, 8, 15, 16, 23, 42]

    : List Nat
  26. [-4, 8, 15, 16, 23, 42] example.idr:2:17:When checking right hand

    side of getTransactions with expected type List Nat When checking argument x to constructor Prelude.List.::: Can't find implementation for Neg Nat
  27. class Account def initialize @balance = 0 end type :balance,

    Nat def balance @balance end type :deposit, Nat, Nat def deposit(amount) @balance += amount end type :withdraw, Nat def withdraw(amount) @balance -= amount end end
  28. class Account def initialize @balance = 0 end type :balance,

    Nat def balance @balance end type :deposit, Nat, Nat def deposit(amount) @balance += amount end type :withdraw, Nat def withdraw(amount) @balance -= amount end end
  29. def withdraw(amount: Nat) @balance -= amount end

  30. def withdraw(Nat amount) @balance -= amount end

  31. def withdraw(Float amount) @balance -= amount end

  32. None
  33. (Fun fact: he knows way more about ‘90s cartoons than

    code.)
  34. Good Change/Bad Change? • Dynamic typing: Trade execution speed for

    programmer speed, flexibility, and metaprogramming magicks • Static typing: Trade programmer speed for execution speed and compile-time checks • Dependent typing: Trade flexibility for ultra powerful compile-time checks
  35. Part 2: What if Ruby Ran in the Browser?

  36. ( )

  37. ( )

  38. None
  39. ['1', '2', '3'].map(parseInt); // => [ 1, NaN, NaN ]

    ['1', '2', '3'].map((n) => parseInt(n, 10)); // => [ 1, 2, 3 ]
  40. It Does! (Sort Of)

  41. https://www.destroyallsoftware.com/talks/the-birth- and-death-of-javascript

  42. None
  43. Good Change/Bad Change? • Server-side only: Keep control over the

    environment but still have to write JavaScript • With the browser (compile-to-JS): Get the wild west of the browser and still have to read JavaScript • WASM: Get the wild west of the browser, but get to write Ruby in all the places
  44. Part 3: What if Ruby Had No GIL?

  45. I Know, I Know • It’s not a GIL anymore

    • GVL is the new GIL • What did I say about @ing me
  46. (Number of post-talk questions is now: 0)

  47. What is the GVL? • The Global VM Lock (formerly

    Global Interpreter Lock) is a mutual-exclusion lock held by a thread • The GVL prevents any other thread from running while the thread holding it is executing • Not all Rubies have a GVL (CRuby does, JRuby does not)
  48. (Want to hear a Ruby joke?)

  49. (Concurrency!)

  50. Concurrency vs. Parallelism • Concurrency: do one thing at a

    time, but constantly switch among them to make progress on all of them • Parallelism: do multiple things at once
  51. Thread Safety • The GVL’s job is to avoid race

    conditions and prevent data corruption • It prevents threads from sharing code unsafely, e.g. Array#<<
  52. Ye Olde Guildes Credit: http://olivierlacan.com/posts/concurrency-in-ruby-3-with-guilds/

  53. Actors?

  54. Stealing from Go def fetch # Lycos, go get it!

    end list_of_urls.each do |url| go fetch url end
  55. Stealing from Clojure list_of_urls.pmap(&:fetch)

  56. (repeatedly #(interleave '(:coffee :panic)))

  57. (repeatedly #(interleave '(☕ )))

  58. (Don’t encourage him.)

  59. Good Change/Bad Change? • With the GVL: thread safety (at

    the cost of performance) • Without the GVL: true parallelism and significant performance gains for CPU-intensive work (at the cost of safety)
  60. TL;DPA • Types: There might be something to be gained

    by introducing gradual typing • Environment: There might be something to be gained by targeting WASM • Parallelism: There’s room in Ruby 3 for all kinds of new concurrency primitives
  61. None
  62. Questions? eric_weinstein = { employer: 'Fox Networks Group', github: 'ericqweinstein',

    twitter: 'ericqweinstein', website: 'ericweinste.in' } 30% off with RUBYCONF30! ->