11 ms·
Nope, lisp without garbage collection isn't feasible. Tried it - didn't work out. Let's start with an ordinary lisp implementation, and replace garbage collecti
by jd 18y ago
Nope, lisp without garbage collection isn't feasible. Tried it - didn't work out. Let's start with an ordinary lisp implementation, and replace garbage collection with stacklocal and manual allocation. Then using a couple of examples I'll show that you end up with a monstrosity.
You can do a lot with stack-local allocation, but not everything. I think it's fair to say that a Lisp without closures is a useless Lisp.
A clever compiler can optimize something like
(print (reduce (list 1 2 3 4) (lambda (x y) (+ y x))))
such that it works without any garbage collection. The list you create is a local variable, the lambda function is a pure function without state (no closure necessary) and reduce is also a pure function.
You might think that if you can do this, you can express almost everything without garbage collection. Unfortunately, not really.
Suppose you have `revere-list` function. E.g.
(reverse-list (list 1 2 3 4)) # '(4 3 2 1)
We previously assumed that the list was a local variable, created as a function argument. Now reverse-list must return a copy of the list, as the original list ceases to exist when the function returns. That's a problem, because it means you have to make deep-copies of every object on function calls. No big deal, you say: a lot of languages call-by-value. Well, yes, but it _is_ a big deal. Because it means you have to introduce & and * so you can describe when you want a by-copy and by-reference assignment.
So you get a lisp with pointers. A lot of fun, but not all that practical.
(= *(elt my-list 3) (+ *(elt my-list 3) 1))
Yes, it's exactly what you think it is. 'elt now returns a reference to a list element, that you have to dereference before assignment. Ugly, but it works right?
Oh no. It gets worse. What if you create a function that returns a reference to a function argument (stack-local!)? Segfault.
A lisp with pointers that can segfault at any point? That's it. I'm going back to C.
I've skipped a lot of steps here (I could go on for hours), so you have to read really carefully to see how every problem is a logical consequence of each assumption. Sorry for that...
I've been trying to find the perfect balance between stack-allocation (RAII) and garbage collection, and it's a lot tougher than it seems.