Skip to content

Instantly share code, notes, and snippets.

@saikyun
Created April 18, 2020 06:12
Show Gist options
  • Save saikyun/906b19e466b1f2e83e5bd48e8f43dc0c to your computer and use it in GitHub Desktop.
Save saikyun/906b19e466b1f2e83e5bd48e8f43dc0c to your computer and use it in GitHub Desktop.
(ns miracle.thread
(:require [clojure.pprint :refer [pprint]]
[clojure.string :as str]
[clojure.walk :refer [postwalk]]))
(defn used-vars
[form]
(let [vars (transient [])]
(postwalk (fn [f]
(when (and (symbol? f)
(str/starts-with? (name f) "$"))
(conj! vars f))
f)
form)
(persistent! vars)))
(defn has-var?
[form]
(seq (used-vars form)))
(comment
(used-vars '(a b c))
(used-vars '(a b (let [x $1] (+ x x))))
(has-var? '(a b c))
(has-var? '(a b (let [x $1] (+ x x))))
)
(defn fix-fun-call
[sym form]
#_(if sym
(if (seq? form)
(if (has-var? form)
form
(concat form [sym]))
(list form sym))
form)
(let [new-form (if sym
(if (seq? form)
(if (has-var? form)
form
(concat form [sym]))
(list form sym))
form)]
`(try ~new-form
(catch Exception ~'e
(println "Exited at:" '~new-form)
~@(for [v (used-vars new-form)]
`(println (str "(def " '~v " " ~v ")")))
(throw ~'e)))))
(defn handle-form
[res forms]
(if (empty? forms)
res
(let [[form & more] forms]
(cond
(nil? form) res
(and (symbol? form)
(= form '_))
(let [[form & more] more]
`(do ~(fix-fun-call res form)
~(handle-form res more)))
(and (symbol? form)
(str/starts-with? (name form) "$"))
(let [sym form
[form & more] more]
(if (and (seq? more)
(symbol? (first more))
(= (first more) '|))
(let [f form
[_ err-f & more] more]
`(do (try
(let [~sym ~(fix-fun-call res form)]
~(handle-form sym more))
(catch Error e#
(let [~sym (~err-f e#)]
~(handle-form sym more))))))
`(let [~sym ~(fix-fun-call res form)]
~(handle-form sym more))))
(and (seq? more)
(symbol? (first more))
(= (first more) '|))
(let [f form
[_ err-f & more] more]
`(do (try
~(handle-form res (concat [f] more))
(catch Exception e#
(~err-f e#)))))
:else
`(let [~'$last ~(fix-fun-call res form)]
~(handle-form '$last more))))))
(defmacro =>>
[& forms]
(handle-form nil forms))
(name 'aoe)
#_(pprint (macroexpand '(=>> 1
inc
(* 2))))
#_(pprint (macroexpand '(=>> 1
$1 inc | #(println %)
_ (println "$1 is" $1)
(* 2))))
#_(->> -1
inc
(#(/ 2 %)))
;;=> Divide by zero
(=>> -1
inc
_ (println "curr") ;; _ means "skip this step"
(/ 2))
(=>> -1
inc
_ (println "curr") ;; _ means "skip this step"
(#(/ 2 %)))
;;=> curr 0
;;=> Divide by zero
(=>> -1
inc
_ (println "curr") ;; _ means "skip this step"
$v inc ;; $v means "store in $v"
_ (println "$v =" $v)
(#(/ 2 %)))
;;=> curr 0
;;=> $v = 1
;;=> 2
(=>> -1
inc
_ (println "curr")
(#(/ 2 %)) | (constantly 1337))
;;=> curr 0
;;=> 1337
(=>> 1
$1 (do (throw (Error. "HEHE")) (inc $last))
| (fn [err]
(println "Error:" (-> err Throwable->map :via first :message))
10)
_ (println "$1 is" $1)
(* 2))
(=>> 1 inc (* 2))
(comment
(=>> [1 2 3]
(map inc)
(filter #(<= 3 %)))
(->> [1 2 3]
(map inc)
(filter #(<= 3 %)))
(defn handle-form
[v forms]
(if (empty? forms)
v
(let [[form & more] forms]
(cond
(nil? form) v
:else (let [f# (if v
(if (seq? form)
(concat form [v])
(list form v))
form)]
(handle-form f# more))))))
(defmacro =>>
[& forms]
(handle-form nil forms))
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment