I'll post the source of the interpreters on github in this and future posts and highlight some of my findings in more detail in the posts. I am not going to write and explain too much about the languages themselves, there are plenty of books and tutorials for that purpose, just highlights :)
F# is part of the ML family and largely compatible with OCaml. It's one of the new hybrid functional / OO languages (like Scala, Clojure etc) that the kids are raving about these days. This means it can expose and interact with .NET libraries and objets code seamlessly. It also have a whole host of other functionality like active patterns, asynchronous workflows and (soon) type providers that I will get back to in future posts.
Let's start with discriminated unions which is a very powerful way of concisely describing (in this case) the syntax of the language;
This is means what it reads, "a scheme expression is either empty or a list of expressions or a list of listtypes or ...". It really can't be any clearer than that now can it?
ML's pattern matching is just fantastic when writing parsers, well any code really. This is how the evaluator of Expressions look like;
This is the famous recursive eval/appy loop as described in SICP. Of all the languages I've written this in, nothing is as concise and readable as ML. The main match statement is basically a switch, but there are a few subtleties here. For instance the Combination matches have a nested pattern separating the empty () case and list (head::tail) case.
The interactive Read-Eval-Print-Loop (REPL) also deserves a shout out, this is using the F# pipe operator that passes the result of a function to the (last) parameter of another. So that try/catch is basically saying;
- read a line from the console
- convert it to a list
- parse that list
- take the head (first element) of the list (this is the expression)
- evaluate it
- call itself recursively
All the code can be found here, there are few bugs (see failing tests) that I might fix later, or maybe you are up for it! :)