Programming ≈ Fun

Grokking the Ruby Blocks in 10 Minutes

I am assuming you are intrigued about Ruby blocks. My assumption is that you are aware that they exist but unsure of what they are or how to use them. From my experience main obstacle in understanding them is introduction of multiple concepts all at once. You need to understand closures and procs to understand blocks. Also Ruby mix-up with lambda vs. proc debate is not helpful either. There are some great posts about the subject. For example Understanding Ruby Blocks Procs and Lambdas.

Nightmare at 20,000 Feet
Nightmare at 20,000 Feet via Wikipedia

I am going to bluntly ignore the details and just give the 20,000 feet look at it.

Block in Ruby is just another type of variable.

Memorize the Concepts Not the APIs

I was always ashamed of not being able to bang out code without looking at the documentation. One example was file opening/handling in .NET 1.1. I remember not being able to do it even if my life would depend on it. Later on I’ve read that Microsoft made the study about APIs usability. One of the APIs that missed the mark was the IO.

The main complaint was that you need way too many lines of code for basic scenarios.
The other complaint was that you need the knowledge of rather abstract (from the usage point of view) inheritance tree. That was a bit of relief. I stopped feeling as such an imposter that was getting payed for doing nothing. Still I regarded this as my flaw and was always irritated when unable to do simple stuff because I forgot API details.

Similarly, after finding out about Ruby I was amazed that alpha geeks figured it out five years before me. When I think about it more carefully, it would not be logical any other way. I speculate that they were able to position Ruby as a Smalltalk derivate that has some Perl syntax sugar and some Lisp functional goodness. That enabled them to label/recognize the whole technology relatively fast and easy.

Breaking the Rules

Yesterday I’ve subscribed to Rubies in the Rough from James Edward Gray II and read his article “Doing it Wrong”.

In his article he questions (along with some other rules) the rule of never using regular expression for xml parsing.

As it turned out it was a fortunate move since six dollars and one day latter I came across .xml that needed to be parsed.

I have a confession to make: I’ve always hated xml parsers. This particular .xml did not even use xml strengths; data inside was all messed up:

<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Exchage rates list</title>
<link>http://*******</link><description>Excange rates list 12/13/2011</description><item>
      <guid isPermaLink="false">code: 978</guid>
      <title>EMU (EUR)</title>
      <description>
          Unit: 1<br />
          Buying: 1.95583  <br />
          Medium: 1.95583  <br />
          Selling: 1.95583 <br />
      </description>

  </item>   <item>
      <guid isPermaLink="false">code: 36</guid>
      <title>Australia (AUD)</title>
      <description>
          Unit: 1<br />
          Buying: 1.488813<br />
      ...

Small Sample of Ruby Elegance

If you don’t know Ruby please take a few moments and look at code below. You may like it.

w = %w[a c d b e] # same as w = ["a", "c", "d", "b", "e"]
w.sort #=> ["a", "b", "c", "d", "e"]
w.sort.reverse #=> ["e", "d", "c", "b", "a"]
w.sort { |a,b| b<=>a } #=> ["e", "d", "c", "b", "a"]

w.reduce(:+) #=> "acdbe"
w.map(&:upcase) #=> ["A", "C", "D", "B", "E"]

w.include? "a" #=> true

(1..8).select(&:even?) #=> [2, 4, 6, 8]
(1..8).reject(&:even?) #=> [1, 3, 5, 7]

langs = %w[ruby python perl] # same as langs = ["ruby", "python", "perl"]

langs.group_by(&:chr) #=> {"r"=>["ruby"], "p"=>["python", "perl"]}
langs.map(&:capitalize) #=> ["Ruby", "Python", "Perl"]

As they say:

The beauty of Ruby is found in its balance between simplicity and power.

If after this your mouth is watering, you can try Ruby online.

Quality Is Overrated

I’ve been a TDD zealot for the last 7-8 years. I take pride in my code being well tested, my solutions being user friendly and my design being test driven.

When I test I know my system works. I sleep like a baby. I have a balls of brass. I can embrace change and laugh at how easy it is to add new requirements.

The thing is, in my life I’ve seen a fair amount of big systems that are terrible. They all have one thing in common. Everybody hates them. Programmers, users… but they do work, sort of. They are slow and buggy but nevertheless they deliver some value to the users.

Enterprise is euphemism for lame systems that barely work for 300 users?

Oddly, in many of those terrible systems funny thing happened. After a while guess what? People involved (users and programmers) made those terrible systems work (just enough) and all of a sudden you have a winner. Bigger the system, bigger the win. Bigger the mess, bigger the ecosystem of additional companies making it all work.

Think Windows & antivirus for example.

I wonder how smug IBM felt when developing OS/2 with all the cool stuff…and than a big nothing happened. Right now you might be thinking that I’ve lost it. You are ready to click away… but let see some examples:

Blow Your Mind (Maybe) With Case Equality in Ruby

It all starts with “A Little Unnecessary Smalltalk Envy” from Bob Hutchinson.

Quick warning: If you don’t like monkey patching… Run away now it is still not too late…

# Copied from
# http://blog.teksol.info/2007/11/23/a-little-smalltalk-in-ruby-if_nil-and-if_not_nil
# http://recursive.ca/hutch/2007/11/22/a-little-unnecessary-smalltalk-envy/
# Bob Huntchison
# Shortened to just support if_not_nil
class Object
  def if_not_nil(&block) yield(self) if block end
end

class NilClass
  def if_not_nil(&block) end
end

This enables you to stop treating nil as a special case:

class Person
  attr_reader :name
  def initialize(name)
    @name = name
  end
end

def person_that_exists
  Person.new("drKreso")
end

def non_existing_person
  nil
end

person_that_exists.if_not_nil { |person| puts "found #{person.name}"} # => found drKreso
non_existing_person.if_not_nil { |person| puts "found #{person.name}"} # => nothing happens

Refactoring My Basement

A rather unfortunate series of events led me ending up in my basement with a task of cleaning it up. It was mildly put a mess, this photo was taken shortly after refactoring has begun. I was unable to even go inside and therefore forced to put half of the stuff in the hall.

Faking Multiple Blocks in Ruby

Three months ago I was comparing Lisp, Smalltalk and Ruby. I was struggling to create new language syntax (for example my version of if..else) that is so easy to do in Lisp, and also possible in Smalltalk:

In Smalltalk it would be used like this:

(1 = 1)
    ifCorrect:    [Transcript show: 'I am correct']
    ifNotCorrect: [Transcript show: 'I am wrong'].
My knowledge of Smalltalk is non-existing, but look at the beautiful [] block syntax and notice the keyword arguments being able to accept multiple blocks.

Implementation in Smalltalk is both straightforward and cool:

# this is in True class
ifCorrect: trueAlternativeBlock ifNotCorrect: falseAlternativeBlock
     ^trueAlternativeBlock value

# this is in False class
ifCorrect: trueAlternativeBlock ifNotCorrect: falseAlternativeBlock
     ^falseAlternativeBlock value

In Ruby I was missing the ability to have multiple blocks in method call that would enable me to evaluate only one leg. This was best I could come up with and it included (mis)using the lambdas:

class FalseClass
  def if_correct(trueBlock, hash)
    hash[:if_not_correct].call
  end
end

class TrueClass
  def if_correct(trueBlock, hash)
    trueBlock.call
  end
end

(1==0).if_correct ->{ print "Hooray it's true"},
       if_not_correct:->{print "Not true"}

Today I’ve read the excellent post about using Ruby Blocks as Dynamic Callbacks. I was mesmerized, but of course I didn’t get it. Than I saw really kick ass explanation here. Holding hands did have effect even on me. Still I am not sure that I would be able to pull it of on my own without watching the original code. At the end I did saw one gist in comments claiming to have similar pattern. I don’t know if it’s better, but it looks less intrusive because there is no patching of Proc class and it clicked more easily.

Decorators in Ruby

The decorator pattern is used to extend the functionality of a certain object in a runtime. In a statically typed language you need to define decorator interface, then subclass from it and initialize the component (object) that you are decorating.

In Ruby you can pledge: “Yes I am a grownup” and skip the formal interface definition part.

In either case the payoff comes with the fact that you can combine “extensions” without writing out complex inheritance tree that accounts for all possible combinations. Therefore you end up using extension that you need when you need them.

Let’s check it out on Wikipedia coffee example.

class Coffee
  def cost
    1
  end
  def ingredients
    %w(coffee water sugar)
  end
end

If we want some latte, we can create a new decorator for the coffee:

class Latte
  def initialize(component)
    @component = component
  end
  def cost
    @component.cost * 1.2
  end
  def ingredients
    @component.ingredients << "milk" << "whipped cream" << "vanilla"
  end
end

Favorite Vim Tools & Tricks

I’ve been using Vim for the last two years. It did take some getting use to, but the idea clicked almost instantly. Having normal and insert mode is superior concept in my mind. It allows you to treat text editing as a game.

I am not a power user by far but I do have some favorite tricks.

Using console version

  • Pros:
    • Console output is colored
    • Ctrl-y puts you to console, fg puts you right back
    • No need to open console in another window
  • Cons:
    • Color scheme is a bit uglier (less color in console)
    • Copy paste is a bit harder (from other GNOME apps, at least for me)

I’ve tried everything here. Rationally I thought that the console version is too ugly. BUT I noticed that I type vim from terminal unconsciously. The Ctr-y/fg combo and ability to start test to console from within vim sealed the deal. Somehow I got use to lack of prettier color scheme.