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

A Comprehensive Degree of Ruby 2.3

A Comprehensive Degree of Ruby 2.3

A wide-ranged look at the newly released Ruby 2.3 - covering everything from the pragmatic, blog-popular methods (the safe navigation operator, Hash#dig, etc) to performance increases (HTML escaping is now up to 7x faster!)and the experimental features to save and load instruction sequences for Ruby's virtual machine.

Chris Arcand

March 10, 2016
Tweet

More Decks by Chris Arcand

Other Decks in Programming

Transcript

  1. Chris Arcand
 chrisarcand chrisarcand www.chrisarcand.com A Comprehensive Degree of Ruby

    2.3
  2. None
  3. None
  4. Let’s talk Ruby!

  5. Ruby 0.95 (first public release!) - December 21st, 1995 Ruby

    2.3.0 (latest release) - December 25th, 2015 Ruby is 20 years old!
  6. The I-clicked-the-link-on-Hacker-News-or-Twitter summary: •“#dig!” •“Frozen string literalz! I can haz

    performance?”* •“Hash comparisons!” •“OMGOMGOMG THE SAFE NAVIGATION OPERATOR!!!” •“The did_you_mean gem!” •“OMG did you see there’s a safe navigation operator?” * Careful, here
  7. Today: • Everything from the previous slide, in detail •

    Some methods: • Array#bsearch_index • Enumerable#grep_v • Hash#fetch_values • Hash#to_proc • Module#deprecate_constant • Numeric#positive? && #negative • and more… • New Squiggly Heredoc syntax • A few performance improvements (ie CGI#escapeHTML) • A few removals (Bye bye, Rake!; $SAFE removals)
  8. Lots to cover! View the full changelog at https://github.com/ruby/ruby/blob/v2_3_0/ChangeLog Since

    Ruby 2.2.0: 2946 files changed 104057 insertions(+) 59478 deletions(-)
  9. ✨ Removals ✨

  10. So long, Rake! (sorta) [Feature #11025] Rake is removed from

    the standard library (kind of) Part of a larger effort to gemify all the things:
 https://bugs.ruby-lang.org/issues/5481
  11. Be $SAFE! [Feature #5455] $SAFE=2 and $SAFE=3 are obsolete. If

    $SAFE is set to >=2, an ArgumentError is raised.
  12. –Some person sitting in this room right now 
 “Uhhh…cool

    story bro…”
  13. “WTH is $SAFE?” All external data is dangerous. Don't let

    it close to interfaces that can modify your system.
  14. “WTH is $SAFE?” The variable $SAFE determines Ruby's level of

    paranoia
  15. “WTH is $SAFE?” The variable $SAFE determines Ruby's level of

    paranoia
  16. Language changes ✨ ✨

  17. ArgumentError: wrong number of arguments (2 for 1)

  18. None
  19. Improved ArgumentError message [Feature #9025] >> some_method("foo", "bar") ArgumentError: wrong

    number of arguments (2 for 1)
  20. Improved ArgumentError message [Feature #9025] 
 1 for 0? 2

    for 3? STAHP! >> some_method("foo", "bar") ArgumentError: wrong number of arguments (2 for 1) >> some_method("foo", "bar") ArgumentError: wrong number of arguments (given 2, expected 1)
  21. did_you_mean ? [Feature #11252] The did_you_mean gem by Yuki Nishijima

    is included in Ruby 2.3’s bundled_gems
  22. >> methosd # => NameError: undefined local variable or method

    `methosd' for main:Object # Did you mean? methods # method
  23. >> OBject # => NameError: uninitialized constant OBject # Did

    you mean? Object
  24. >> full_name = "Yuki Nishijima" >> full_name.starts_with?("Y") # => NoMethodError:

    undefined method `starts_with?' for "Yuki Nishijima":String # Did you mean? start_with?
  25. Heredoc: <<- class FancyHello def self.hello puts <<-README.inspect Hello World!

    README end end FancyHello.hello # => ???
  26. " Hello\n World!\n" Note that the while the closing identifier

    may be indented, the content is always treated as if it is flush left. If you indent the content those spaces will appear in the output. From syntax documentation:
  27. class FancyHello def self.hello puts <<-README.inspect Hello World! README end

    end FancyHello.hello
 # => "Hello\n World!\n"
  28. Rails implements it’s own method to avoid this

  29. “Squiggly Heredoc”: <<~ [Feature #9098] As proposed by Avdi Grimm

    This syntax strips indent from the quoted string:
  30. …Ok…fine. The Safe Navigation Operator ✨ ✨ That’s it! See

    you in Ruby 2.4!
  31. Safe Navigation Operator [Feature #11537] “&.” can be used to

    ‘safely navigate’ a chain of methods even as something in the chain returns ‘nil’
  32. • Common in Ruby:
 if user && user.address && user.address.valid?

    • ActiveSupport implements #try:
 user.try(:address).try(:valid?) • Ruby 2.3’s new operator:
 user&.address&.valid?
  33. • Common in Ruby:
 if user && user.address && user.address.valid?

    • ActiveSupport implements #try:
 user.try(:address).try(:valid?) • Ruby 2.3’s new operator:
 user&.address&.valid? Coalesces ‘false’ Does not coalesce ‘false’
 More like #try! of ActiveSupport Be warned: These aren’t exactly the same thing:
  34. Interesting tidbit… From Georgi Mitrev (@gmitrev) nil&.nil? 


  35. Interesting tidbit… nil&.nil? # => nil
 From Georgi Mitrev (@gmitrev)

  36. Interesting tidbit… nil&.nil? # => nil
 nil?.nil? # => false

    nil.nil? # => true From Georgi Mitrev (@gmitrev)
  37. Frozen String Literal options [Features #11473, #11725] Ruby 2.1: “str”.freeze

    was optimized
 to reduce object allocation • # frozen_string_literal: true 
 at the top of each file (magic comment or pragma) • --enable-frozen-string-literal
 flag on the command line (ALL string literals by default!)
  38. string = “I LOVE this talk!”
 puts string.gsub!(“LOVE, “HATE”) ./thoughts.rb

    `ruby thoughts.rb` # => “I HATE this talk!”
  39. ./thoughts.rb `ruby --enable-frozen-string-literal thoughts.rb` thoughts.rb:2:in `gsub!': can't modify frozen String

    (RuntimeError) from thoughts.rb:2:in `<main>' string = “I LOVE this talk!”
 puts string.gsub!(“LOVE, “HATE”)
  40. • Immutability -> Performance! • Immutability -> Thread safetyer •

    Literal value === Literal value (same object)
  41. • Potentially numerous compatibility issues in the RubyGems ecosystem •

    In the Ruby world, most programs have dozens or hundreds of third party dependencies • Dare we say: Is this Python 3 all over again? • Is it really that much faster? (only literals!) ✋
  42. TLDR: Pay attention

  43. ✨ Core Class Changes ✨

  44. This is annoying: params[:order] && params[:order][:shipping_info] && params[:order][:shipping_info][:country]

  45. params[:order][:shipping_info][:country] rescue nil This is slow and stupid:

  46. params.fetch(:order, {}) .fetch(:shipping_info, {}) .fetch(:country, nil) This is mega annoying:

  47. #dig [Feature #11643, 11688]

  48. #dig [Feature #11643, 11688] Array, Hash, and Struct all have

    a #dig method
  49. { a: 1, b: 2 }.include?({ a: 1 })

  50. { a: 1, b: 2 }.include?({ a: 1 }) #

    => false ☹
  51. { a: 1, b: 2 }.include?(:a) # => true Hash#include?

    is an alias of #has_key?
  52. Hash Comparison Methods [Feature #10984] Hash#<=, Hash#<, Hash#>=, Hash#> A

    really helpful table from Olivier Lacan (who originally proposed hash comparisons)
  53. In RSpec: expect({ a: “billy”, b: “bob” }) .to include({

    b: “bob” }) expect({ a: “billy”, b: “bob” } > { b: “bob” }) .to be_truthy { a: “billy”, b: “bob” } > { b: “bob” } # => true
  54. ✨ Performance ✨

  55. • CGI::escapeHTML optimized (aka: Completely rewritten) • Array#select!, Array#keep_if, Array#reject!,

    and Array#delete_if no longer changes the receiver array instantly every time the block is called. [Feature #10714] Performance is now linear • Misc Ruby virtual machine improvements
  56. CGI::escapeHTML optimized ~7x faster worst case ~3x faster best case

    (heavy replacements) (no replacements)
  57. ⚠ ERB template rendering in Rails uses this method So…?

    Among many things, Great benchmark done by Alexander Dymo here:
 http://ruby-performance-book.com/blog/2016/02/is-ruby-2-3-faster-rails-erb-template-rendering-performance.html ~4x speedup for Rails template rendering
  58. Experimental Features ✨ ✨ (There’s only one…)

  59. RubyVM::InstructionSequence

  60. RubyVM::InstructionSequence

  61. Ruby 2.3 adds #to_binary, #load_from_binary as an experimental feature:

  62. This is experimentation for providing "machine dependent" binary files. •

    Faster bootstrap time for big applications(?) • Reduced memory consumption(?)
  63. Nothing new A simple precompiled file cache: • Python: .pyc

    and .pyo files • Java: .class files • C/C++: .o files • Ruby: Rubinius uses .rbc files! ¯\_(ϑ)_/¯
  64. In brief… • Enumerable#grep_v - inverse version of Enumerable#grep [Feature

    #11049] • Hash#fetch_values - stricter version of Hash#values_at [Feature #10017] • Module#deprecate_constant - gives deprecations on any constant [Feature #11398] • Numeric#positive? and Numeric#negative? - Like Rails! [Feature #11151] • String#[email protected] and String#[email protected] - to make mutable/frozen string literals [Feature #11782] • Array#bsearch_index - complement to Array#bsearch [Feature #10730] • Thread#name, Thread#name= - Thread names! [Feature #11251] • Hash#to_proc - Can use a Hash to iterate over an Enumerable [Feature #11653] • ObjectSpace methods added, #count_symbols, etc… [Feature ???lol??]
  65. Ruby 2.3 Summary • The true beginning of what’s to

    come in Ruby 3 (Frozen string literal pragma, CLI options) • Some great user experience improvements (did_you_mean, ArgumentError message, better Heredoc, etc) • A few very useful methods/syntax (#dig, hash comparisons, #grep_v, #bsearch_index, Numeric#postive?/negative?, etc) • Internal house cleaning (Rake is a gem, $SAFE levels removed, etc) • Minor performance increases (CGI.escapeHTML and VM improvements)
  66. None
  67. Questions? 
 chrisarcand chrisarcand www.chrisarcand.com While I'm not working in

    the open source community that might be supporting your project, I could be working directly on it for you! I'm available as a part-time contractor to help your project flourish. See me afterward or visit http://chrisarcand.com/forhire/