elm-city-craftworks/course-001 — pull request #9 by eregon (2014-05-17 13:12:37+00:00)
Title: Minimal Calc implementation

This PR includes the practical exercises of part 3 without any extra.

However, there are some interesting aspects in it:
* We have an error when the parsing fails (how is 0 fine for a missing variable?), we just need to remove the `/* none */` case.
* We can negate entire expressions `-(2*x)`.
* Rationals are supported *with a single call changed* once floats where added. This is achieved by calling `Rational` instead of `Float` when parsing a number, and so `4/6` is `Rational(4) / Rational(6)`. It makes sense to call `Rational` for floats so `/` is consistent (it never is integral division).
* We have tokenize-time missing variable errors, how early is that? (not such a good idea in general but since we can do it in this restricted language ...)
* Variables lookup happens at tokenize-time so we need not to touch the parser.
* The way to quit is sending an EOF (Ctrl+D in a terminal). The original code did not handle `gets` being nil. This handles cases like `echo "2*4" | ruby calc.rb`.
* We actually have less lines than the original file (you know I value conciseness).

A trick I relatively often use is to use `eval` as a Parser, especially to import some large data-structure from a similar-looking language.
In this case it would be as simple as `ruby -rmathn -e 'x=10; p eval ARGV[0]' -- 'x * 3'`

BTW, The chapter 8 "Implementing Lisp in Ruby" in the book Practical Ruby Projects is a great example of implementing some simple language, one step at a time.