Week 1: Ruby

As I mentioned last week, I'm trying to work through the book Seven Languages in Seven Weeks by Bruce Tate this winter. This first week was about the object-oriented language Ruby.

Week 1 ˙ Week 2 ˙ Week 3 ˙ Week 4 ˙ Week 5 ˙ Week 6 ˙ Week 7

Introduction

For this first post in the series, I'll start with a few comments about the book. Bruce Tate has a straight-forward writing style and seems to have put a lot of thought into the choice of seven languages to cover (i.e. they span a few different programming paradigms). The Introduction provides some background on those choices and also some advisories about what to expect from the book. For example, he warns that he doesn't tell the reader how to install any of the languages. This was no problem for me as all but one (Io) were available in the Ubuntu repositories.

In flipping through the other chapters, it appears that the structure of the chapter on Ruby is typical, so I'll say a bit about it here. Aside from a brief introduction and some concluding thoughts (on the strengths and weaknesses of the language), it is split into three "days". Each day had walkthroughs of some features of the language with example code and then a self-study section with suggestions of things to look up and problems to solve. Having a full-time job, I often split the walkthrough and self-study over separate days. Over the course of the week, I'd estimate I put about 6 hours into it.

My previous programming/scripting experience has been in procedural languages (R and octave) so the object-oriented and functional languages in Seven Languages in Seven Weeks will be a stretch for me—hopefully I can learn some new ways of approaching problems.

With this prelude out of the way, the rest of the post will share some of my notes about Ruby. These will include notable methods, some quotes from Bruce Tate, links for further reading, and a few annotated code snippets. I expect future posts in this series (which will likely take more than 7 weeks to get through, especially if I have to travel for my job during this timeframe) to follow a similar format. Later on, I have a few mini-projects in mind that I may apply the languages from the book that I like best to; however, learning the language and trying a project in a single week is too much.

Notes on Ruby

Here is how Bruce Tate describes Ruby:

As a language, Ruby is an interpreted, object-oriented, dynamically typed language from a family of so-called scripting languages. Interpreted means that Ruby code is executed by an interpreter rather than a compiler. Dynamically typed means that types are bound at execution time rather than compile time. In general, the trade-off for such a strategy is flexibility versus execution safety, but we'll get into that a little more later. Object-oriented means that the language supports encapsulation (data and behavior are packaged together), inheritance through classes (object types are organized in a class tree), and polymorphism (objects can take many forms).

Here are some notes on methods and objects in Ruby that I thought seemed especially relevant or useful:

  • conditional statements (if and unless) can be used in three ways: the traditional if condition then statement end; in reverse as statement if condition; the terse form of condition ? statement : alternative. Loops with while and until work in a similar way. Ruby also allows for loops.
  • The .each method enumerates all the contents of an object (e.g. cells in an array).
  • Square brackets are used to refer to an element in an array (e.g. array[0] for the first element; a negative index starts from the end).
  • Two dots indicates a range (e.g. 1..10).
  • To convert between data types (where possible), .to_i, .to_s, .to_f, .to_a go to integers, strings, floats, and arrays, respectively.
  • puts prints a string to the console (or open file) and gets reads a string from the keyboard (so use .to_i to make it a number).
  • Arrays are flexible objects. You can have arrays of arrays and non-homogenous (e.g. mixture of strings and integers) arrays. They can even be treated as stacks with the .push and .pop methods.
  • Hashes are similar to arrays, but instead of having a numeric index you assign a key to each entry (using key => value). Hashes are entered inside of curly braces. Access their contents with .keys or .values, respectively.
  • To replace part of a string, .gsub("old text", "new text") can be used. #{variable} can put variable text into a string (as long as it is in double quotes, not single quotes which are always taken literally).
  • .times can be used with an integer to repeat a code block a set number of times.
  • Code blocks are functions without names. They go between curly braces (on a single line, normally) or between do and end (spread over multiple lines). Vertical pipes (|variable(s)|) pass variables to the code block.
  • Powerful operations are available on objects that are comparable and enumerable: .any?, .all?, .sort, .max, .member?, .select, .collect, .map, .find, .inject, etc.
  • .match is used with regular expressions (more on that below).
  • To access a file, use File.open("filename", "r"); replace the r (for read) with w (for write) or a (to append), as applicable.
  • If a method doesn't exist, Ruby goes to .method_missing, which can be given custom behaviour in a Class—the author showed some examples of ways this could be used as a short-cut.

Here are some links for further reading/research:

  • In addition to the book chapter, I went through this brief tutorial.
  • Here is a diagram of core Classes in Ruby.
  • This free ebook was recommended in Seven Languages in Seven Weeks.
  • This interactive site lets you test the behaviour of some regular expression searches.

Finally, here are a few snippets of code from exercises in the book that illustrate some of the syntax and features of Ruby:

 

This defines a hash (the keys are words in English and the entries are translations in other languages—Duolingo likes making sentences with words like these so they came to mind pretty quickly) then iteratively prints the values from it:

my_hash = {'apple' => ['pomme', 'manzana'], 'woman' => ['femme', 'mujer'], 'eats' => ['mange', 'come']}
my_hash.each {|key, value| puts value}

This opens a file then prints lines that match a regular expression (a very basic regular expression that is just looking for the word "puts"):

File.open("selfstudy1.rb", "r").each do |line|
  puts line if /(puts)/.match(line)
end

This example shows a range and how to insert variable text into a string:

(1..10).each do |number|
  puts "this is sentence number #{number.to_s}" 
end

This interactive session peeks at the hierarchy of Classes for a number object (I used 4):

irb(main):033:0> 4.class
=> Fixnum
irb(main):034:0> 4.class.class
=> Class
irb(main):035:0> 4.class.superclass
=> Integer
irb(main):036:0> 4.class.superclass.superclass
=> Numeric
irb(main):037:0> 4.class.superclass.superclass.superclass
=> Object
irb(main):038:0> 4.class.superclass.superclass.superclass.superclass
=> BasicObject
irb(main):039:0> 4.class.superclass.superclass.superclass.superclass.superclass
=> nil

Without previous experience in object-oriented programming, a week wasn't really enough time to get the hang of Modules or metaprogramming in Ruby. I'm not even entirely sure of my understanding of classes yet. However, there is another object-oriented language (Scala) in Seven Languages in Seven Weeks, so that chapter should help provide more exposure to those concepts.

The language in the next chapter is Io.

Permalink