From One End to the Other in Ruby

A while back I tackled the following programming challenge: From One End to the Other: Find the smallest possible (positive) integer that ends in a six such that if that six is removed and placed in front of the remaining digits of the number, the resulting number will be four times as large as the original. My solution is below, and here: https://gist.github.com/jwworth/5a5b3647a44b9a782896 I like that this solution is relatively fast, at 0.36 seconds. I like that it doesn’t imply what the answer might be by having a ceiling to the search— the code will run forever if my conditional is wrong. I like that it uses the rotate method, something I didn’t know existed until I tried to solve this problem. ...

March 6, 2016

Variable Hoisting in Ruby

This afternoon my pair and I spent quite a while on a subtle bug. The culprit? Variable hoisting. Take this file: class Test def self.hoist require 'pry'; binding.pry; bar = 1 end end Test.hoist When we hit the PRY debugger, what will the value of bar be? I would have thought it would raise NameError, because bar has seemingly not yet been defined. Wrong: $ ruby test.rb From: /test.rb @ line 4 Test.hoist: 2: def self.hoist 3: require 'pry'; binding.pry; => 4: bar = 1 5: end [1] pry(Test)> bar => nil When Ruby parses a file, it ‘hoists’ each variable to the top of its scope, declaring and setting it to nil, even if that variable is never assigned by our code. So variables inside an if false conditional get hoisted and set to nil, as described in this blog post. ...

February 10, 2016

Succeed, Precede, and Surround in Haml

Haml’s design makes HTML and Ruby tricky to mix inline. But we have Haml helper methods to make it easier. Here is succeed in action: Developer at = succeed ', ' do = link_to "Hashrocket", "https://hashrocket.com/" This becomes: Developer at <a href="https://hashrocket.com/">Hashrocket</a>, Notice the comma at the end, outside of the a tag? precede and surround work in a similar fashion, and do what we’d expect. http://haml.info/docs/yardoc/file.REFERENCE.html#succeed

January 6, 2016

Ruby's Kernel::abort

Today I used Ruby’s Kernel::abort for the first time. It’s one of those incredibly useful methods I can’t believe I’ve never seen before. Observe: # abort.rb {1} def no_message abort end def message abort('Process terminated') end $ irb 2.2.2 :001 > require './abort' => true 2.2.2 :002 > no_message $ irb {1} 2.2.2 :001 > require './abort' => true 2.2.2 :002 > message Process terminated $ Use it to bail from a script. ...

November 5, 2015

Accessor Performance Gap

This week I learned that attr_reader is more performant than a simple getter method. Here’s a gist from five years ago where Aaron Patterson explains: https://gist.github.com/pjb3/629716 I ran that same benchmarking script today on Ruby 2.2.3. The gap has narrowed, but still exists: ruby-2.2.3 Rehearsal ----------------------------------------------- method 0.070000 0.000000 0.070000 ( 0.074840) attr_reader 0.050000 0.000000 0.050000 ( 0.052603) -------------------------------------- total: 0.120000sec user system total real method 0.070000 0.000000 0.070000 ( 0.072229) attr_reader 0.050000 0.000000 0.050000 ( 0.053374) I like attr_reader because it’s a Ruby convention and is one line instead of three. Now, I also like its performance relative to a getter. ...

October 25, 2015

Fetch Your Environmental Variables

It’s important to fetch Ruby environmental variables rather than directly referencing them. This code depends on ‘secret_key’: key = ENV['secret_key'] When ‘secret_key’ is not set, ‘key’ will be assigned nil, which is an object. Later, a call to key.upcase will produce a NoMethodError, because Ruby doesn’t know how to uppercase nil. This is better: key = ENV.fetch('secret_key') Now, when ‘secret_key’ is not set, KeyError will be raised. The code fails fast. fetch takes a second argument as a default, which means you can even prevent KeyError entirely, if you choose. ...

September 26, 2015

Ruby Regex Literal

Ruby has a nice percent string literal for regular expressions, %r. It’s like // but allows your regex to contain backslashes without escaping them. Check it out: 2.1.0 :001 > 'http://google.com'.gsub(/http:\/\/google.com/, 'fine') => "fine" 2.1.0 :002 > 'http://google.com'.gsub(%r{http://google.com}, 'better') => "better" As the example implies, this is useful when matching URLs. Documentation

September 10, 2015

Building a Markov-Chain MVP in Ruby

Project announcement! Last night I built a Markov Chain-generated novel, titled Ceramic Nation. It’s presented as a robot named Ellis Champlin, who is diligently composing one chapter a day based on a corpus of classic public-domain novels and philosophy texts. Here is the site and source code. This was an exercise in rapidly building an MVP, styling, testing, Dev Opsing, and Markov-chaining. I’m curious what this bot will produce as the days go on, and am hoping for greatness. I plan to refine the logic slowly to produce better and better chapters, and rotate the source documents as I am inspired by new books and ideas. ...

September 11, 2015

Keyword Precedence

The Ruby keyword not and the unary ! aren’t the same. They have a different precedence, and therefore are not interchangeable, despite seeming very similar. irb > not 3 == 4 => true irb > !3 == 4 => false The first example is evaluated as not (3 == 4), or not false, which is true. The second example is evaluated as (not 3) == 4, or false == 4, which is false. ...

July 2, 2015

Skid Keywords

Ruby has a few interesting old keywords that use the underscore, or ‘skid’, to convey meta information about the file. Here they are in action: # test.rb puts __ENCODING__ puts __FILE__ puts __LINE__ __END__ Because this is after 'end', it should not be executed Running this file produces: $ ruby test.rb UTF-8 test.rb 3 Pretty cool!

July 2, 2015