Day 2 is about defining things, functions, classes, as well as a second look at basic containers.
Blocks are covered as well. It is hard to overstate their importance in making a language flexible and expressive. In a language like Ruby with regular evaluation (i.e. not lazy), blocks (with an unobtrusive syntax) are essential to implement embedded DSL (alternatives are laziness, as in Haskell, or more selective mechanisms to control evaluation, such as lisp’s macros, or Io’s method call meta-API).
But that’s a topic for another book (which I really look forward to reading).
Back to this one.
Print the contents of an array of sixteen numbers, 4 numbers at a time
The implementation is simple enough, the values are accumulated until there’s enough. I’m using the p printing command because neither puts nor print do exactly what I need: puts prints each element on a different line; print does not add a newline.
First self.h_to_children: its purpose it to turn a list of key, value pairs (each key being a String, and each value a Hash or nil) into a list of Trees. It uses the collect method to transform each key, value pair into a Tree (recursively converting the value on the way).
self.build takes the list of Trees; if there’s only one, it is our root. Otherwise, it creates a new root, using the list of Trees as children.
As stated in the book, it is very simple to implement a basic grep function in Ruby. Here’s one that relies on the magic variable ARGF (oddly enough, it is documented as a constant of the Object class):
Certainly there must be a better way. The code below is an attempt at that. Some of the complexity comes from my attempt to mimic the original grep behaviour when dealing with one or many files. With only one file, it does not print the file name. With many, it does.
Also, I revert to reading from ARGF.read when there is no filename, that is, when I should read from stdin (which ARGF.read does when ARGV is empty).
Finally, if there are file names to iterate over, I need to check for errors, print a statement, and continue.
The new code has a function to make a header from the file name if needed (that is, when there are more than one file to process).