Skip to content

Instantly share code, notes, and snippets.

@mtnygard
Created April 3, 2018 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mtnygard/c786c67f5bb98cac883116c45330158c to your computer and use it in GitHub Desktop.
Save mtnygard/c786c67f5bb98cac883116c45330158c to your computer and use it in GitHub Desktop.
Use macros to make nested try/catch with values less of an eyesore.
(defn -main
[& args]
(let [file (try-> args
parse-args
(:! clojure.lang.ExceptionInfo ei (fe/print-other-exception ei))
:filename)]
(when (and file (not= ::try/exit file))
(try-> file
fern/load-from-file
(:! java.io.FileNotFoundException fnfe (fe/print-error-message (str "File not found: " (pr-str (.getMessage fnfe)))))
fern/prepare-service
(:! Throwable t (fe/print-evaluation-exception t file))
a/start-service
(:! Throwable t (fe/print-other-exception t file))))))
(ns com.cognitect.vase.try)
(defmacro try->
"Thread the first expression through the remaining expressions.
A form like (:? classname var ,,,) catches exceptions from
the preceding code. It continues threading with the value of the
body expressions as the replacement value.
A form like (:! classname var ,,,) catches exceptions from the
preceding code, but does _not_ continue threading. It aborts and the
entire expression returns ::exit"
[x & forms]
(loop [x x
forms forms]
(if forms
(let [form (first forms)
threaded (cond
(and (seq? form) (= :! (first form)))
(with-meta `(try ~x (catch ~@(rest form) ::exit)) (meta form))
(and (seq? form) (= :? (first form)))
(with-meta `(try ~x (catch ~@(rest form))) (meta form))
(seq? form)
(with-meta `(let [v# ~x]
(if (= ::exit v#)
::exit
(~(first form) v# ~@(next form)))) (meta form))
:else
`(let [v# ~x]
(if (= ::exit v#)
::exit
(~form v#))))]
(recur threaded (next forms)))
x)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment