Skip to content

Instantly share code, notes, and snippets.

@saikyun
Last active April 17, 2020 09:23
Show Gist options
  • Save saikyun/3df90ad70e9afaac465c8b21f1707542 to your computer and use it in GitHub Desktop.
Save saikyun/3df90ad70e9afaac465c8b21f1707542 to your computer and use it in GitHub Desktop.
control flow macro
(ns miracle.monad
(:require [clojure.pprint :refer [pprint]]))
;; make clj-kondo happy
(def | ::err)
(defn handle-form
[forms]
(if (empty? forms)
nil
(let [[form & more] forms]
(cond
(nil? form) nil
(= (first more) '|)
`[(try
~@(handle-form [form])
~(let [e (gensym "error")]
`(catch Error ~e
(~(second more) ~e))))
~@(handle-form (drop 2 more))]
(and (seq? form)
(= (first form) 'def))
`[(let [~(second form) ~(nth form 2)]
~@(handle-form more))]
more `[~form ~@(handle-form more)]
:else [form]))))
(defmacro =>
[& forms]
`(do ~@(handle-form forms)))
(pprint
(macroexpand
'(=> (def res (merge {:name "Jona", :cat "Charlie"})) ;; "define"
(=> (def res (merge res {:friend "sogaiu"}))
(println "inner print" res)
(def cool-number (rand-int 2))
(when (= 1 cool-number)
(throw (Error. "cool-number was 1"))))
| (fn [err]
(println "handling error" (-> (Throwable->map err) :via first :message))
#_ (throw err) ;; you can re-throw it if you want
)
(def res (merge res {:wife "Cindy"}))
(println "outer print" res))))
(=> (def res (merge {:name "Jona", :cat "Charlie"})) ;; "define"
(=> (def res (merge res {:friend "sogaiu"}))
(println "inner print" res)
(def cool-number (rand-int 2))
(when (= 1 cool-number)
(throw (Error. "cool-number was 1"))))
| (fn [err]
(println "handling error" (-> (Throwable->map err) :via first :message))
#_ (throw err) ;; you can re-throw it if you want
)
(def res (merge res {:wife "Cindy"}))
(println "outer print" res))
@saikyun
Copy link
Author

saikyun commented Apr 17, 2020

result of running:

miracle.monad=> (load-file "<...>/monad.clj")

;; pprinted macroexpand
(do
 (clojure.core/let
  [res (merge {:name "Jona", :cat "Charlie"})]
  (try
   (=>
    (def res (merge res {:friend "sogaiu"}))
    (println "inner print" res)
    (def cool-number (rand-int 2))
    (when (= 1 cool-number) (throw (Error. "cool-number was 1"))))
   (catch
    java.lang.Error
    error4902
    ((fn
      [err]
      (println
       "handling error"
       (-> (Throwable->map err) :via first :message)))
     error4902)))
  (clojure.core/let
   [res (merge res {:wife "Cindy"})]
   (println "outer print" res))))

;; actual result
inner print {:name Jona, :cat Charlie, :friend sogaiu}
handling error cool-number was 1
outer print {:name Jona, :cat Charlie, :wife Cindy}
nil

miracle.monad=> (load-file "<...>/monad.clj")

;; pprinted macroexpand
(do
 (clojure.core/let
  [res (merge {:name "Jona", :cat "Charlie"})]
  (try
   (=>
    (def res (merge res {:friend "sogaiu"}))
    (println "inner print" res)
    (def cool-number (rand-int 2))
    (when (= 1 cool-number) (throw (Error. "cool-number was 1"))))
   (catch
    java.lang.Error
    error4934
    ((fn
      [err]
      (println
       "handling error"
       (-> (Throwable->map err) :via first :message)))
     error4934)))
  (clojure.core/let
   [res (merge res {:wife "Cindy"})]
   (println "outer print" res))))

;; actual result
inner print {:name Jona, :cat Charlie, :friend sogaiu}
outer print {:name Jona, :cat Charlie, :wife Cindy}
nil

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment