This blog post was originally posted on my blogpost blog at this URL, and was later migrated to this place. There may be some comments at the original URL.
Out of a whim, I retook Factor yesterday. By some coincidence, Alvaro Videla also happened to retake it at about the same time. In a twitter conversation on the topic, he asked a couple of interesting questions. Since twitter is not a suitable medium for elaborate discussions, I am posting my responses here.
Note that I am only a beginner in Factor, and I am trying to answer the questions on the basis of whatever little I know. If there are any errors in this post, please feel free to correct.
A: Factor macros have considerably simpler semantics. Thanks to “concatenativity”, macro expansion simply involves splicing a sequence. Nothing more. Thanks to the same property, Factor macros, unlike their Lisp counterparts, compose.
One downside I can think of is that Factor macros provide no mechanism for maintaining hygiene. You are on your own. Probably because relying on named cells isn’t in the vein of the language. Or probably it was just an oversight. I don’t know. (Perhaps I should pop the question to the wizards at #concatenative.)
Note that macros aren’t used very often in Factor. Factor uses parsing words for most things that Lisps use macros for. (Parsing words are kind of like reader macros.)
A: Comparing against this list:
- Conditionals: Check.
- Function types: Check. In Factor parlance, functions are called words. Words are simply named quotations; quotations are sequences; sequences are data. So even function “contents” are first class values. Ergo, in this respect, it goes even further than Lisp. This enables crazy things like invertible quotations.
- Recursion: Check. With full TCO. Note that in Factor you rarely use recursion directly in your code. Sequence combinators can usually achieve the same ends in a more elegant manner.
- Variables 2.0: Check.
- GC: Check.
- Programs composed of expressions: Check.
- Symbols: Check.
- A notation for code using tree of symbols: Irrelevant.
- The whole language always available: Check.
Factor meets all key stated goals of Lisp. There are many similarities between the two. You can see a clear Lisp influence in many aspects of Factor. Even so, it is not a Lisp.
The stack model is quite different from Lisp’s inside-out model. It necessitates things like
fry, not required in Lisp. Rest parameters have no meaning in a stack language context, and so it’s a common idiom to define words specialized for arities upto a certain value (usually 3) and a general word that operates on a sequence. Keyword arguments don’t exist either. (On the other hand, there are plentiful advantages to the stack model as listed on concatenative.org.)
More importantly, Factor is concatenative whereas Lisp is applicative. What this means is that Factor doesn’t have lambdas as part of the language. Nor let bindings. (There exists a library support for both but they desugar to tacit expressions.) So, no connection with lambda calculus. Factor is more in line with Backus’ function-level programming than with lambda calculus, although the official Factor site and blog do not appear to touch upon these topics.
For what it’s worth, on my personal awesomeness scale, Factor lies way above Lisp.