Skip to content

Instantly share code, notes, and snippets.

@semperos
Created July 20, 2016 02:05
Show Gist options
  • Save semperos/04a7f753a7905cb565e53a41158a6040 to your computer and use it in GitHub Desktop.
Save semperos/04a7f753a7905cb565e53a41158a6040 to your computer and use it in GitHub Desktop.
Generate car, cdr, cadr, cdar, etc. in Clojure
(ns semperos.hs
(:require [clojure.string :as str]))
(defn strip-first-last
"Strip first and last letter from string."
[s]
(subs (subs s 1) 0 (- (count s) 2)))
(def step-fns {\a first \d next})
(defmacro defcarcdr
[name]
(when-not (and (str/starts-with? (str name) "c")
(str/ends-with? (str name) "r"))
(IllegalArgumentException. (str "defcarcdr expects car, cdr, cadr, etc., but you gave '" name "'.")))
(let [steps (->> (strip-first-last (str name))
(map step-fns)
reverse)]
`(def ~name (fn [coll#] (-> coll# ~@steps)))))
(defn defcarcdrs
[num-steps]
(doseq [n (reverse (range 1 num-steps))]
(let [choices (into [] (for [x [\a \d]] x))
fors (into [] (mapcat (fn [_] [(gensym) choices]) (range n)))]
(doseq [combo (eval `(for ~fors (mapv first (partition 2 ~fors))))]
(let [name (symbol (str "c" (apply str combo) "r"))]
(eval `(defcarcdr ~name)))))))
(defcarcdrs 5)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment