It's fascinating the relationship between Lisp and Forth. I am quite sure there is something about these two old simple languages and the concept of duality in mathematics that we are missing.
It's fascinating the relationship between Lisp and Forth. I am quite sure there is something about these two old simple languages and the concept of duality in mathematics that we are missing.
https://en.wikipedia.org/wiki/Concatenative_programming_lang...
It's ridiculously elegant.
I had just implemented type inference[1] when I got smashed over the brain by Prolog. So now the Python code is in limbo because the Prolog implementation of Joy is blindingly elegant[2].
In Prolog, the Joy interpreter is also the Joy type inferencer.[2]
The compiler (from Joy expressions to new Prolog rules) is five lines long.[2]
[1] http://joypy.osdn.io/notebooks/Types.html
[2] https://osdn.net/projects/joypy/scm/hg/Joypy/blobs/tip/thun/...
Yes, there's a real connection between concatinative languages and logic languages. In some sense you can think of a concatinative logic language as Joy with the ability to push "unknown" values onto the stack, as well as a few constraint manipulatives. That's somewhat orthogonal, but it makes sense an interpreter for Joy would be quite compact in prolog.
Thanks for the links, I'll review your work later!
You might also like: http://conal.net/papers/compiling-to-categories/
He transforms Haskell to a point-free form that's suspiciously like Joy... ;-)
Is there more to the relationship than "Lisp is written as a preorder tree, and Forth is written as a postorder tree"?
Longer answer: actually another common feature is that both can execute code at compile-time (macros).
Full answer: really, no. They are fundamentally different: Lisp is a decent symbolic language, Forth is a decent portable assembler.
In Lisp we know that (eql 1 2 3) is a "too many arguments" error. It doesn't just take 1 2 from the stack, push back the answer, and leave 3 beneath it.
Lisps are actually fairly conventional block-structured languages, having more in common with Pascal than with Forth. Lexical scopes, local variables, function calls with arguments going to formal parameters and all that.
That error also comes from the semantics. You can't tell that (eql 1 2 3) is a too-many-arguments error just by looking at the tokens. That could be a 3-ary function, or an "eql is not a function" error.
The parentheses in Lisp code certainly suggest a particular tree structure, but they don't require it by virtue of their graphical form. And once you're willing to look up the arity of functions, Forth is written directly in its own tree structure to exactly the same degree that Lisp is, just with structural markers elided.
Think about it another way: a classmate in compilers class asked me once how Lisp handled operator precedence. Obviously, with the tree structure of the code fully specified, Lisp doesn't handle operator precedence because the question can't arise.
Note that this is just as true of Forth.
Also, Lisp supports variadic functions with the same safety. Delimitation of arguments is necessary for variadic functions, like list.
The structure of every top-level form is an actual tree object in memory that is constructed before anything else happens. It can be walked by macros, or quoted so that the program accesses it as data directly.
Basically, nothing like Forth.
This is not the case; you can easily have a Forth word that consumes however many arguments as are on the stack.
Currently my preferred language is Racket because it is so fun and practical, reminds me of the earlier days of Python but much more thought out. You write you code (which is fun) and you have an executable all within one setting.
I think the magic bit with Forth is that it's easy to see how to write one by the time you've finished Starting Forth.
I wish there was an easy checklist: Create stack data structure, create return stack, create primitives ...etc.