July 2009 Archives

On Ruby's elegance and Perl's lack of it

| 3 Comments | No TrackBacks
I've been programming Perl for a number of years and I like the language a lot. It's my weapon of choice when tackling some random programming task or just spiking something quickly. One thing that has bothered me over the years and surprised me to an extent is Perl's rather lousy reputation. It's criticized for being just line-noise, hard to read and generally frowned upon by people outside the Perl community. But Perl is a very flexible and powerful language. True you can write incomprehensible Perl, just as you can write gibberish in most any other language, but you can certainly write good, clean OO code. You just have to know what you are doing (or use Moose which is quite superb at covering up the transgressions of the Perl OO system). I recently picked up a copy of The Ruby Programming Language and the more I read the more it dawned on me just how much Ruby has gotten from Perl. This is no secret as the wikipedia page on Ruby spells out quite clearly. Yet Ruby is considered clean, elegant and straight-forward and has a much better reputation than Perl. Why is this? I decided to dig a little deeper. One point is that in Perl your effort, at least when new to Perl, must be on keeping the code from going all over the place and in Ruby you have to really try if you're gonna write sloppy style. Wherein lies the actual differences?

The regex syntax

The regular expression syntax is quite similar in Ruby and Perl in that it's expressed directly with // and not requiring you to instantiate an Regex object first like in C# or Java. Perl:
print "match" if  $string =~ /\w+?/;
Ruby:
puts "match" if string =~ /\w+?/
But here's where Ruby fanatical devotion to the Pope, er, objects comes into play. In Perl you can choose to compile the regex once to avoid multiple regex engine compilations in a loop and store it in a variable. But all access to groups is done via $1, $2 etc. . In Ruby this creates a new object of the Regexp class hich you can either assign to a variable to use it multiple times or pass around or call methods on. Ruby:
regex = /\w+?/
puts "match" if regex.match("foo")

# or:

/\w+?/.match "foo"
and the match function returns MatchData object(s) which can be used for further digging. An you've got all sorts of cool functions like union which returns a Regexp object which will match all the patterns given as arguments. Doing that in Perl can be very messy. All in all Ruby regexp handling can look like Perl's but goes much further and gives you a lot more flexibility to do what you want in a clean and readable manner.

Variables and nested data structures

First there are to important distinctions: perl use special symbols on variables to indicate variable type, $ for scalars, @ for arrays and % for hashes. Ruby uses (fewer) symbols for indicating variable scope, namely $ for global variables, @ for instance variables, and @@ for class variables. For local variables you do without a sigil. But the more interesting point here is the syntax for defining nested hash tables and arrays in combination with these. defining an hash of arrays in Perl:
my %hash = ( 'key' => [ '5', '3', '1' ] );

#or as a reference directly

my $hash =  { 'key' => [ '5', '3', '1' ] };
and in Ruby
hash =  { 'key' => [ '5', '3', '1'] }

#or with symbols as key

hash = { :key => [ '5', '3', '1'] }
Quite similar. But when we want to access the inner hash and use that one directly, for instance in a sort, look what happens when we have to de-reference the array ref inside the hash: Perl:
my %hash = ( 'key' => [ '5', '3', '1' ] );
@sorted = sort @{ $hash{'key'} };

#or with custom block for sorting reverse

@sorted = sort { $b <=> $a } @{ $hash{'key'} };
Ruby:
hash = { :key => [ '5', '3', '1'] }
sorted = hash[:key].sort

#or with custom block for sorting revers
sorted = hash[:key].sort { |a, b| b <=> a }
Much less noise in the ruby version and I can certainly see that the Perl version, which wouldn't be regarded as line noise at all to seasoned Perl programmer, could look intimidating to a java programmer. But the ruby way is more elegant. And it's all about perception.

Block syntax

While we're at it, let's look at block syntax. This is not so much a noise issue as a power issue which also contributes to cleanliness in the code. Ruby's block syntax with parameters as we saw in the previous example can be used for all sorts of cool things. A block is also an object in Ruby, which it isn't in Perl.
hash = { :b => "foo", :a => "bar" }

hash.each { | key, value | puts "#{key}: #{value}" }

# or a multiline do..end block

hash.each do | key, value |
  puts "#{key}: #{value}"
end
Let's take an example comparing map() from Perl and Array.map in Ruby (including quoting array values to clean things up a bit in both Perl and Ruby).
@array = qw(a b c d e f);

#transform array to ASCII value for the elements
@chars = map { ord } @array;
array = %w{a b c d e f}
chars = array.map { |x| x[0] }
In this example the Perl version looks cleaner to me, but it will fail spectacularly when you need more than one parameter into the block. Ruby handles any number of block arguments, while Perl only has the one value from the data structure you're mapping. This makes the Hash.each_pair (with a block) very useful in Ruby while you cant really do the same without either using a foreach on the keys or values or using map() on the keys and accessing values in the block. If you need both the key and the value inside the block that is. More code and less elegance.

Closing points

  • Ruby's do..end syntax generally cleans up the language a bit, since this is in use for modules, classes, methods and blocks. Perl has only {} and this combined with other brackets and special characters can induce noise.
  • Combination of block or loop syntax with pattern matching can give a noisy appearance.
    @array = ( [1, 2, 3], [4, 5, 6], [7, 8, 9]);
    map { push @joined, sort { $b <=> $a } @{ $_ } }  @array;
    
    and in ruby:
    array = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]
    joined = Array.new
    array.each { |x| joined.push(x.sort { |y,z| z <=> y }) }
    
    Still not all that bad to a Perl hacker, but still.
  • Ruby OO strictness saves you a lot of typing if you're comparing to old school Perl OO. Moose takes much of that away nowadays.
  • Ruby's policy of optional parenthesis both on most method calls and if-statements removes some line-noise factor but can be less readable to the untrained eye. But you get used to it pretty quickly.

Keyboard layout and remapping for fun and profit

| No Comments | No TrackBacks
After having lived with some annoying CAPS-LOCK mishaps and a general feeling of pain in the lower forearm, I decided to remap my keyboard layout for a smoother programming experience. Since I'm Norwegian and use a Norwegian keyboard layout, I have to resort to AltGr+0 to produce a }. Brackets are equally far away. Parenthesis are shift+8 and shift+9 on the number row and all this means moving the hand away from the home row a lot. I wanted to be able to program and maintain my hands in a more or less touch typing position.The goal was improved speed at programming and less discomfort. The fact that I daily program on both windows and linux ( both native and via the cygwin X server) made things a bit more complex than anticipated, as we will see. This article tackles re-mapping the caps-lock key in windows and creating a new keyboard layout in both windows and linux (Xorg that is). Info about re-mapping the caps-lock key under linux is just a google search away. The following setup was used in this little adventure:
  • Windows XP running Cygwin.
  • Ubuntu 9.04 (as X client only)
  • Xorg server 1.5.7 with Xkb packages running in cygwin.

Caps lock remapping

The caps lock key is irritating and I've never used as far as I can tell. But I haven't gotten around to doing anything about it. Now's the time. First I thought about remapping it to control and binding a lot the characters I want more accessible to ctrl+ bindings. This messes with application shortcuts a lot so I went for altGr instead. I used a small program named KeyTweak to perform the binding. The result of running that program is that i new value is written to the registry. It looks like this:
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout]

"Scancode Map"=hex:00,00,00,00,00,00,00,00,02,00,00,00,38,e0,3a,00,00,00,00,00
Either apply the file or do it from within KeyTweak and the caps lock key is now an AltGr key. A reboot is probably in order to put it into effect. It is windows, after all.

Keyboard layout for windows

I used a Microsoft tool called Microsoft Keyboard Layout Creator which is a nice tool for creating a new layout from scratch or basing it on an existing layout. It has some limitations however in that you can't remap things like caps lock and the windows key. But on the other hand it generates nice install packages for your keyboard layout. I decided on the following keyboard shortcuts (remember caps lock is now AltGr so it is easily available for the left pinky finger):
	AltGr+a = !
	AltGr+s = #
	AltGr+d = @
	AltGr+f = $
	AltGr+g = (
	AltGr+h = )
	AltGr+j = /
	AltGr+k = \
	AltGr+l = ~
	AltGr+ø = =
	AltGr+æ = +
	AltGr+u = {
	AltGr+i = [
	AltGr+o = ]
	AltGr+p = }

Keyboard layout for linux/ Xorg

When applying the custom layout for windows this worked well for native windows apps, but when logging into the linux servers and X-forwarding apps to the cygwin X server, it naturally didn't work. A similar custom keyboard layout for the X server was needed. I found a great detailed guide on creating keyboad layouts for X11/Xorg with XKB. There are some steps involved:
  1. Copy the layout you want to base you new layout on to a new file in /usr/share/X11/xkb/symbols.
  2. Tweak it to your liking.
  3. Add it to the list of supported keyboard layouts in /usr/share/X11/xkb/rules/xfree86.lst
  4. Restart your X server and use setxkbmap to set it, or add it in xorg.conf
The interesting parts of the symbols file looks like this:
key { [	u,	U,	braceleft,		uparrow ] };
key { [	i,	I, 	bracketleft,	idotless ] };
key { [	o,	O,	bracketright,	Ooblique ] };
This snippet maps e.g. AltGr+u to braceleft which displays a nice left curly brace. The format is broken down like this:
  • The key name AD07 is the 7th (07) alphanumeric (A) key from the left of the fourth row (D) from the bottom. Bottom row is A, second to bottom B and so on.
  • First column is character displayed when the key is pressed normally
  • Second column is character displayed when the key is pressed with shift down
  • Third column is character displayed when AltGr is down
  • Fourth column is character displayed when both AltGr and shift is down
Key names can be found in /usr/X11/include/X11/keysymdef.h The keyboard layout is exactly the same as for windows and I just based it on the standard Norwegian layout and called it progn (pun intented). The entire progn keyboard symbols file is available for download. So now I have remapped the keyboard to my liking in both Linux and windows. I'll probably tweak the keymappings a bit after some use, but generally I'm very happy with them.
References:

Videos from Lean & Kanban 2009

| No Comments | No TrackBacks
A nearly complete set of videos of the talks at the Lean &amp; Kanban 2009 conference in Miami is available at <a href="http://www.sep.com/lk2009">http://www.sep.com/lk2009</a> with talks from among others Corey Ladas on <a href="http://leansoftwareengineering.com/ksse/scrum-ban/">scrumban</a>, Alan Shalloway on going beyond Toyota, David Anderson on Kanban, Karl Scotland on Kanban flow and cadence and Amit Rethore on why agile isn't enough. All familiar names from the kanbandev Yahoo group which I started to follow recently.

Now I just hope I find enough time to watch some of them.

mini bio

Knut Haugen [Knu:t Hæugen], Norwegian software developer with a penchant for dynamic languages and anything to with developer testing. Agile methodology geek with bias on Lean and Kanban. Some pointers to other stuff by me

meta

This page is an archive of entries from July 2009 listed from newest to oldest.

August 2009 is the next archive.

Find recent content on the main index or look in the archives to find all content.