Building a Lisp from scratch with Swift
uraimo.com
uraimo.com
I find it to be a great tool for both learning about Lisp and the language you're writing your mal implementation in.
$ git clone https://github.com/akkartik/wart
$ cd wart
$ ./wart
ready! type in an expression, then hit enter twice. ctrl-d exits.
mac (foo x)
`(+ ,x 1)
=> (object function {sig, body})
(foo 3)
=> 4
(foo @(list 3)) # apply analogous to the ,@ splice operator
=> 4
(foo @'(3))
=> 4
More info at http://akkartik.name/post/wart. Lots of example programs at http://rosettacode.org/wiki/Category:Wart.I have no plans to extend it.
A similar project I've considered: write an Algol compiler in assembly. Algol is another elegant, influential language originally implemented in assembly.
One benefit of this is that continuations become trivial to implement (they're just a snapshot of the call stack at a given point).
Admittedly, almost all write-your-own-Lisp tutorials omit this, and use a bunch of recursive calls (in the implementation language) instead, which makes it very hard to do TCO, continuations or anything else that requires a real call stack (exception tracebacks, for example).
(I hope this answer makes sense; it's 3 in the morning here, so clarity might suffer a bit. ;-) But as it happens, I am writing a (hopefully non-toy) Lisp interpreter myself, in Go, so the question attracted my interest.
You can go full metacircular and have the interpreter throw an exception and introspect its traceback, in languages that support that.
[1] https://www.uraimo.com/2016/05/05/recursive-tail-calls-and-t...
As other's have mentioned, TCO and first class continuations tend to go together
FWIW, in my rite-of-passage lisp-in-C implementation the type of nil and () is nil, just like the car or cdr of nil: http://akkartik.name/post/wart
$ sbcl
* (symbolp nil)
T
* (listp nil)
T
* (consp nil)
NIL
Is there a boolean predicate? My Common Lisp is rusty and I don't see one at https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node73.html#S....Can you suggest any example Common Lisp programs that print the _types_ NULL or NIL or T? Or show off the benefits of this spindle arrangement? I can intuitively see the benefits of this approach, but an example makes things much more memorable.
;; catch-all method for any type
(defmethod foo ((arg t)) ...)
;;
(defmethod foo (arg ...) ...) ;; alternative spelling: omit class
NIL is the empty list and that is mnemonic for "empty type". For instance, the intersection of two mutually exclusive types is the empty type. Nothing can be both a cons and an atom, so the type denoted by the type expression (and cons atom) is empty; and that is nil. The set manipulation which underlies types needs an empty set, and nil fill the need for that empty set (pun intended).NULL is useful in writing methods that capture NIL (the only instance of NULL). That may be recognized as the "null object pattern":
(defmethod foo ((arg null))
;; (foo nil) called
)
(defmethod foo ((arg number))
;; (foo <number>) called
)
(defmethod foo ((arg t))
;; (foo <anything else>) called
)Nope, because everything is a Boolean: NIL is false, and everything else is true.
(defun booleanp (x) (TYPEP x 'BOOLEAN))