Created
July 20, 2016 02:05
-
-
Save semperos/04a7f753a7905cb565e53a41158a6040 to your computer and use it in GitHub Desktop.
Generate car, cdr, cadr, cdar, etc. in Clojure
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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