Close
Glad You're Ready. Let's Get Started!

Let us know how we can contact you.

Thank you!

We'll respond shortly.

LABS
Ruby 2.1.0 changes of note.

The Ruby 2.1.0

Illustration of a cut ruby.

Release is nearly a month old, so its well past time to look over the changes and uncover the features least discussed.

This release received relatively exceptional social coverage. The attention largely due to the addition of Generational Garbage collection. A bit of exploration reveals changes that may have been overlooked in the shadow of RGenGC.

private def

:def now returns a symbol, a clearer return response then the former nil


irb(main):001:0> def hello
irb(main):002:1> end
=> :hello

Coupled with new private and protected methods now take in a symbol:


class Offer
  def == other
    if self.class == other.class
      salary == other.salary
    else
      super
    end
  end

  def initialize(compensation)
     @compensation = compensation
  end

  protected def salary
    @compensation
  end
end

irb(main):150:0> Offer.protected_instance_methods
=> [:salary]

Required keyword arguments


class Offer
  def initialize(compensation:, position: "Engineer")
    @position = position
    @compensation = compensation
  end
end

Mark the compensation attribute as required by omitting its default value.


irb(main):170:0> Offer.new(compensation: 70000)
=> #
irb(main):171:0> Offer.new(compensation: 70000, position: "Sales Analyst")
=> #
irb(main):172:0> Offer.new(position: "Sales Analyst")
ArgumentError: missing keyword: compensation

Enumerable.to_h

Now we can take any enumerable and derive a hash from it.


(1..10).collect{|a|[a,(a * 2)]}.to_h

Array#to_h

Array implements to_h separately


[[:name, :age], ["Matz", 48]].to_h

#to_h is a convenience method that has been a long time coming.

Refinements

Refinements build a sandboxed around the duck punching / monkey patching of core classes such as numeric.


module CurrencyDecorator
  refine Numeric do
    def to_currency
      sprintf("%s%0.2f", { :currency => "$", :number => self})
    end
  end
end

class Currency
  using CurrencyDecorator

  def initialize(numeric)
    @number = numeric.to_f.to_currency
  end
end

Currency.new returns an implicit conversion of any Numeric param to a decorated stringified float conforming to currency format. All within the safe confines of Currency object.


irb(main):052:0> Currency.new 45.888
<Currency:0x007fd6db0e19b0 @number="$45.89">
irb(main):054:0> Currency.new 79987.87666767
<Currency:0x007fd6db0e19b0 @number="$79987.88">

Numeric outside Currency is unaffected.


irb(main):017:> 748.to_currency
NoMethodError: undefined method `to_currency' for 748:Fixnum

irb(main):018:0> 748.9.to_currency
NoMethodError: undefined method `to_currency' for 748.9:Float

Updates in Std lib

Vector finally implements cross product


Vector[0.6, 0, 0].cross_product Vector[0, 1.4, 0]

Leveraging GMP

The GNU Multiple Precision Arithmetic Library

Large performance increase for calculations involving Bignums

Bignum and Fixnum respond to bit_length


human_population = 10900000000
human_population.bit_length
=> 34
(human_population * human_population).bit_length
=> 67

Thats the quick tour of the less hyped changes

Next I’ll be running through Ruby Koans to explore behavioral differeinces

Comments
  1. Peter Jaros says:

    Actually, `public`, `private`, and `protected` have taken symbols since at least Ruby 1.8. It’s just more useful now that `def` returns a symbol.

  2. I’m curious as to why Array implements `.to_h` separately, and why this is important. I would have expected it to just use the Enumerable implementation.

    Any idea why this is?

  3. Mark says:

    Thanks for this. Just a heads-up I think you’re Currency refinements example isn’t quite right – Currency.new doesn’t care about the return value for initialize – it’ll just return a Currency object. Cheers

  4. Refinements are really cool! I look forward to using them in my code.

    I think there are two problems in your example though. These are:

    1. You are using the keyword-arguments version of `sprintf`, but then refer to the values in the string as “%s” and “%0.2f”. The correct code would be either `sprintf(“%s%0.2f”, “$”, self)` or `sprintf(“%s%0.2f”, { :currency => “$”, :number => self})`.

    2. You seem to be trying to return a string in the initializer, instead of storing it somewhere, or something like that. The examples definitely don’t return what they claim, because a constructor can only return an instance of the class, not of a different class (strings on the examples)

    Just in case it’s relevant, I’m running ruby-2.1.0 on RVM.

  5. Olly Legg says:

    Apologies for nit picking, but your Refinements example has a couple of issues. The Currency initializer will return a Currency instance, not a string as your example suggests. Also your `sprintf` call is mixing two different styles, the format string you’ve specified suggests you meant `sprintf(“%s%0.2f”, “$”, self)` instead.

  6. Matthew Jording says:

    Thanks Olly, updated to reflect intent.

Post a Comment

Your Information (Name required. Email address will not be displayed with comment.)

* Copy This Password *

* Type Or Paste Password Here *