The Little Schemer book club met for the third time last night. Here’s roughly what happened.
Seven of us showed up, and we began by recapping the previous meeting for those who'd missed it. There was a general feeling that some of the discussion from last time had got ahead of the point we’d reached in the book — our collaboratively-built Scheme interpreter barely supported `car` and `cdr`, which meant that the more nuanced conversations (e.g. about how to implement `define` and `lambda`) lacked context.
We decided to work together to get the interpreter to fully support everything in chapter one, with the intention of revisiting the discussion of more complicated ideas once we were ready to actually implement them.
@floehopper cloned http://github.com/tomstuart/little_scheme
onto his laptop and connected it to the projector, while the rest of us gathered round and shouted at him. Together we worked through the failing tests in book order:
* We made the parser support atoms containing non-alphanumeric characters (https://github.com/tomstuart/little_scheme/commit/10b85ef
* We parked the uninteresting problem of how to parse things that aren’t single S-expressions (https://github.com/tomstuart/little_scheme/commit/8b00a2d
) and will return to it if/when it becomes relevant
* We added support for evaluating an atom that isn’t inside a list (https://github.com/tomstuart/little_scheme/compare/8b00a2d...ee82005
* We made `car` and `cdr` raise an exception when applied to an empty list (https://github.com/tomstuart/little_scheme/compare/12f16d6...51cc6bd
), which is our way of reporting “no answer"
* We implemented `cons` on atoms and lists (https://github.com/tomstuart/little_scheme/compare/51cc6bd...de19f86
* We added hacky support for evaluating `cons` (https://github.com/tomstuart/little_scheme/commit/a9016fa
), although none of us were happy with the special-casing required to support an operation with two arguments
* Through a series of satisfying refactorings, we generalised list evaluation to support operations with any number of arguments (https://github.com/tomstuart/little_scheme/compare/cc8142c...40ad8f0
), producing nice code except for a `#send` of a protected method
* We eliminated the nasty `#send` by pushing each case of the `#evaluate` method down onto the `Atom` and `List` classes (https://github.com/tomstuart/little_scheme/commit/9010aae
), which had the added bonus of replacing a conditional with polymorphism
* We implemented `null?` on lists (https://github.com/tomstuart/little_scheme/compare/9010aae...0247aac
), deciding that the `List#null?` predicate should return a Scheme boolean (a `#t` or `#f` atom) instead of a Ruby boolean
* We implemented `quote` (https://github.com/tomstuart/little_scheme/commit/df4b4dd
), gaving us our first encounter with what Little Schemer calls a “keyword” (special-case behaviour inside `List#evaluate`) versus a “primitive operation” (instance method on `Atom` or `List`).
After doing all this, 52 out of the 64 examples were passing; the remaining examples concern `atom?` and `eq?`, which we didn’t have time to implement. Presumably these will be easy to get working at the next meeting, after which we can move on to implementing chapter two.
I enjoyed the meeting a lot. Although we were still working through the absolute basics of the book, it gave us ample opportunity to think about and discuss what we were trying to do in terms of our implementation; hopefully that’ll provide a firm practical grounding for the harder material in future chapters. Thanks everyone!