exercises: quote with macros
authorNicolas Boulenguez <nicolas.boulenguez@free.fr>
Tue, 21 May 2019 20:22:18 +0000 (22:22 +0200)
committerNicolas Boulenguez <nicolas.boulenguez@free.fr>
Thu, 30 May 2019 14:46:04 +0000 (16:46 +0200)
docs/exercises.md
examples/exercises.mal

index f56943d..6fc3963 100644 (file)
@@ -65,6 +65,9 @@ make REGRESS=1 TEST_OPTS='--hard --pre-eval=\(load-file\ \"../answer.mal\"\)' te
   A macro is necessary because a function would attempt to evaluate
   the first argument.
 
+- Implement quoting with macros.
+  The same remark applies.
+
 - Implement `apply`.
 
 - Implement maps using lists.
@@ -85,8 +88,6 @@ make REGRESS=1 TEST_OPTS='--hard --pre-eval=\(load-file\ \"../answer.mal\"\)' te
     the tree and not add those keys when it finds them further down
     the tree.
 
-- Implement quoting within MAL.
-
 - Implement macros within MAL.
 
 ## More folds
index d4793bf..4185692 100644 (file)
              more (rest (rest binds))]
         `((fn* [~key] (let2 ~more ~form)) ~val)))))
 
+(defmacro! quote2 (fn* [ast] (list (fn* [] ast))))
+(defmacro! quasiquote2
+  (fn* [ast]
+    (let* [
+      is-pair (fn* [x] (if (sequential? x) (not (empty? x))))
+      f (fn* [ast]                      ; evaluating its arguments
+        (if (is-pair ast)
+          (let* [a0 (first ast)]
+            (if (= 'unquote a0)
+              (nth ast 1)
+              (if (if (is-pair a0) (= 'splice-unquote (first a0)))
+                (list 'concat (nth a0 1) (f (rest ast)))
+                (list 'cons (f a0) (f (rest ast))))))
+          (list 'quote ast)))
+      ]
+      (f ast))))
+
 (def! apply
   ;; Replace (f a b [c d]) with ('f 'a 'b 'c 'd) then evaluate the
   ;; resulting function call (the surrounding environment does not