labs ruby

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