I am reading Paul Graham's The Roots of Lisp
I have tried converting the function subst
on page 5, which is defined like this:
(defun subst (x y z)
(cond ((atom z)
(cond ((eq z y) x)
('t z)))
('t (cons (subst x y (car z))
(subst x y (cdr z))))))
To its corresponding Clojure
implementation. I do not have production experience in either languages (I have been reading Clojure), so any help would be appreciated since I am reading this to understand the roots of LISP. The closest I came to was this (but it is horribly wrong):
(defn subst
[x y z]
(if (not (nil? z)) z x)
(if (= z y) x z)
(cons (subst x y (first z))
(subst (x y (rest z)))))
This is how I would do it, including a unit test to verify:
(ns tst.demo.core
(:use tupelo.core tupelo.test)
(:require [clojure.walk :as walk]))
(defn subst
[replacement target listy]
(walk/postwalk (fn [elem]
(if (= elem target)
replacement
elem))
listy))
(dotest
(is= (subst :m :b [:a :b [:a :b :c] :d])
[:a :m [:a :m :c] :d]))
However, I would not spend a lot of time reading 40-year old texts on Common Lisp, even though I think Paul Graham's book Hackers & Painters is quite mind blowing.
Clojure has evolved the state-of-the-art for lisp by at least one order-of-magnitude (more like 2, I would say). Major improvements include the use of the JVM, persistent data structures, concurrency, syntax, and data literals, just to name a few.
Please see this list of Clojure learning resources, and maybe start with Getting Clojure or similar.
More from Paul Graham on Clojure