"Traduttore, traditore"
(This can be translated as "translator, traitor", but doing so ruins the pun, which is fun in itself)
It is hard to hint at possible fixes in your Clojure code because the specification is unclear:
if you follow the The Roots of Lisp to the letter, you are going to implement a Lisp on top of Clojure, and subst
might be similar to the one in the book.
But if you want to implement subst
as commonly used in Lisp, the code shown here won't do it.
Even though Clojure has cons
and nil?
functions, they do not mean the same as in Common Lisp (resp. cons
and null
): See clojure: no cons cells for details.
Before you can translate subst
, you have to determine what is the idiomatic thing to do in Clojure.
Typically subst
is used to transform a tree, made of cons cells; note for example that subst
does not recurse into vectors, strings, etc. Among those trees, a particular subset of trees are those which are Lisp forms. In fact, one important use case for subst
is to search-and-replace forms during code generation.
If you restrict yourself to the Clojure Cons
type, you won't support code as data, as far as I know.
Since Clojure code also uses vectors and maps, you probably need to recurse into such objects. So, how to translate subst
is not an easy problem to specify.
A possible starting point is to read LispReader.java
to determine the set of objects that constitute an AST, and see what kind of code walking you want to do.
My advice would be to study those languages independently first. With a bit of experience with each, you will have a better way to see how similar and how different they are with each other.