I want to transfer code from
("AAA" ("BB" 11 #"XXX"))
to
("AAA" ("BB" 11 "YYY"))
I just want to change #"XXX" to "YYY".
I write a function it works.
(defn tt [clause]
(cond (not (sequential? clause)) clause
(and (sequential? clause)
(= 2 (count clause))
(= `deref (first clause))
(string? (second clause)))
"YYY"
:else (map tt clause)))
there is my result:
(tt '("AAA" ("BB" 11 #"XXX"))) --> ("AAA" ("BB" 11 "YYY"))
But when I change the function to macro , it raise exception.
(defmacro test [& clause]
(let [f (fn tt [clause]
(cond (not (sequential? clause)) clause
(and (sequential? clause)
(= 2 (count clause))
(= `deref (first clause))
(string? (second clause)))
"YYY"
:else (map tt clause)))]
(f clause)))
and it raise exception like this
(test "AAA" ("BB" 11 #"XXX")) --> ClassCastException java.lang.String cannot be cast to clojure.lang.IFn
I have test map for prewalk function. Both of them raise exception.
I have no idea what is wrong with it and how to fix this error in macro??
I wrote a macro to handle http response
(defmacro defhandler
[name & args]
(let [[docstring args] (if (string? (first args))
[(first args) (next args)]
[nil args])
args (apply hash-map :execute-if true (vec args))]
`(do
(def ~name
(with-meta (fn [scope# promise#]
(let [e# (:execute-if ~args)
ei# (if (fn? e#)
(e# scope#)
(boolean e#))]
(when ei#
(.then promise# (fn [result#]
(let [{:strs [http-status# value#]} result#
the-func# ((keyword http-status#) ~args)]
(the-func# scope# value#))))))) {:structure ~args}))
(alter-meta! (var ~name) assoc :doc ~docstring))))
So I can do
(defhandler my-handler
:200 (fn [$scope value] (set! (.-content $scope) value)))
But that throws "UnmatchedDelimiter" at line 1, but if I try with a named function:
(defn my-func [$scope value] (set! (.-content $scope) value))
(defhandler my-handler
:200 my-func)
It works ok. I'm just curious, is that a normal behaviour?
That is not the behavior I see when I try your example, nor does it seem very likely. I suggest checking that the forms you pasted here are exactly the ones that produce an error; I suspect your actual anonymous function included one too many )s.
clojure's pre-expr seems cool, but does it possible if I want to raise an Exception when the :pre is false?
thanks.
You can use Dire instead
(ns mytask
(:require [dire.core :refer [with-precondition! with-handler!]]))
(defn add-one [n]
(inc n))
(with-precondition! #'add-one
"An optional docstring."
;;; Name of the precondition
:not-two
(fn [n & args]
(not= n 2)))
(with-handler! #'add-one
{:precondition :not-two}
(fn [e & args] (apply str "Precondition failure for argument list: " (vector args))))
(add-one 2) ; => "Precondition failure for argument list: (2)"
Preconditions are conditions that must be true or else an exception is thrown. If you have a condition where you want an exception to be thrown when false, just complement the conditional or not the result.
user=> (defn magic? [n] (= 0 (rem n 42)))
#'user/magic?
user=> (defn foo [n] {:pre [(magic? n)]} n)
#'user/foo
user=> (foo 42)
42
user=> (defn bar [n] {:pre [(not (magic? n))]} n)
#'user/bar
user=> (bar 42)
AssertionError Assert failed: (not (magic? n)) user/bar
user=> (defn baz [n] {:pre [((complement magic?) n)]} n)
#'user/baz
user=> (baz 42)
AssertionError Assert failed: ((complement magic?) n) user/baz
just started using log4j in one of my home-projects and I was just about to break out the mouse and cut-and-paste (trace (str "entering: " function-name)) into every function in a large module. then the voice of reason caught up and said "there has simply got to be a better way"... I can think of making a macro that wraps a whole block of functions and adds the traces to them or something like that? Any advice from the wise Stack-overflowing-clojurians?
No need for a macro:
(defn trace-ns
"ns should be a namespace object or a symbol."
[ns]
(doseq [s (keys (ns-interns ns))
:let [v (ns-resolve ns s)]
:when (and (ifn? #v) (-> v meta :macro not))]
(intern ns
(with-meta s {:traced true :untraced #v})
(let [f #v] (fn [& args]
(clojure.contrib.trace/trace (str "entering: " s))
(apply f args))))))
(defn untrace-ns [ns]
(doseq [s (keys (ns-interns ns))
:let [v (ns-resolve ns s)]
:when (:traced (meta v))]
(alter-meta! (intern ns s (:untraced (meta v)))
#(dissoc % :traced :untraced))))
...or something similar. The most likely extra requirement would be to use filter so as not to call trace on things which aren't ifn?s. Update: edited in a solution to that (also handling macros). Update 2: fixed some major bugs. Update 4: added untrace functionality.
Update 3: Here's an example from my REPL:
user> (ns foo)
nil
foo> (defn foo [x] x)
#'foo/foo
foo> (defmacro bar [x] x)
#'foo/bar
foo> (ns user)
nil
user> (trace-ns 'foo)
nil
user> (foo/foo :foo)
TRACE: "entering: foo"
:foo
user> (foo/bar :foo)
:foo
user> (untrace-ns 'foo)
nil
user> (foo/foo :foo)
:foo
I am trying to execute a func several times before giving up upon exceptions.
But it is not valid in Clojure to recur from catch block.
How can this be achieved ?
(loop [tries 10]
(try
(might-throw-exception)
(catch Exception e
(when (pos? tries) (recur (dec tries))))))
java.lang.UnsupportedOperationException: Cannot recur from catch/finally
The best I could find is the following clumsy solution (wrapping in func and calling it)
(defn do-it []
(try
(might-throw-exception)
(catch Exception e nil)))
(loop [times 10]
(when (and (nil? (do-it)) (pos? times))
(recur (dec times))))
Macros are calling...
How about this:
(defn try-times*
"Executes thunk. If an exception is thrown, will retry. At most n retries
are done. If still some exception is thrown it is bubbled upwards in
the call chain."
[n thunk]
(loop [n n]
(if-let [result (try
[(thunk)]
(catch Exception e
(when (zero? n)
(throw e))))]
(result 0)
(recur (dec n)))))
(defmacro try-times
"Executes body. If an exception is thrown, will retry. At most n retries
are done. If still some exception is thrown it is bubbled upwards in
the call chain."
[n & body]
`(try-times* ~n (fn [] ~#body)))
kotarak's idea is the way to go, but this question tickled my fancy so I'd like to provide a riff on the same theme that I prefer because it doesn't use loop/recur:
(defn try-times* [thunk times]
(let [res (first (drop-while #{::fail}
(repeatedly times
#(try (thunk)
(catch Throwable _ ::fail)))))]
(when-not (= ::fail res)
res)))
And leave the try-times macro as it is.
If you want to allow the thunk to return nil, you can drop the let/when pair, and let ::fail represent "the function failed n times", while nil means "the function returned nil". This behavior would be more flexible but less convenient (the caller has to check for ::fail to see if it worked rather than just nil), so perhaps it would be best implemented as an optional second parameter:
(defn try-times* [thunk n & fail-value]
(first (drop-while #{fail-value} ...)))
A try-times macro is elegant, but for a one-off, just pull your when out of the try block:
(loop [tries 10]
(when (try
(might-throw-exception)
false ; so 'when' is false, whatever 'might-throw-exception' returned
(catch Exception e
(pos? tries)))
(recur (dec tries))))
My proposal:
(defmacro try-times
"Retries expr for times times,
then throws exception or returns evaluated value of expr"
[times & expr]
`(loop [err# (dec ~times)]
(let [[result# no-retry#] (try [(do ~#expr) true]
(catch Exception e#
(when (zero? err#)
(throw e#))
[nil false]))]
(if no-retry#
result#
(recur (dec err#))))))
Will print "no errors here" once:
(try-times 3 (println "no errors here") 42)
Will print "trying" 3 times, then throw Divide by zero:
(try-times 3 (println "trying") (/ 1 0))
One more solution, without macro
(defn retry [& {:keys [fun waits ex-handler]
:or {ex-handler #(log/error (.getMessage %))}}]
(fn [ctx]
(loop [[time & rem] waits]
(let [{:keys [res ex]} (try
{:res (fun ctx)}
(catch Exception e
(when ex-handler
(ex-handler e))
{:ex e}))]
(if-not ex
res
(do
(Thread/sleep time)
(if (seq rem)
(recur rem)
(throw ex))))))))
This allows catching multiple more then one exception and provides some feedback about the causes for the retries.
(defmacro try-n-times
"Try running the body `n` times, catching listed exceptions."
{:style/indent [2 :form :form [1]]}
[n exceptions & body]
`(loop [n# ~n
causes# []]
(if (> n# 0)
(let [result#
(try
~#body
~#(map (partial apply list 'catch) exceptions (repeat `(e# e#))))]
(if (some #(instance? % result#) ~exceptions)
(recur (dec n#) (conj causes# result#))
result#))
(throw (ex-info "Maximum retries exceeded!"
{:retries ~n
:causes causes#})))))
If you add a result arg to your loop, you can nest the (try) block inside of the (recur). I solved it like this:
(loop [result nil tries 10]
(cond (some? result) result
(neg? tries) nil
:else (recur (try (might-throw-exception)
(catch Exception e nil))
(dec tries))))
Here's yet another approach:
(loop [tries 10]
(let [res (try
(might-throw-exception)
(catch Exception e
(if (pos? tries)
::retry
(throw e))))]
(if (#{::retry} res)
(recur (dec tries))
res)))
But may I also recommend a cool little trick, instead of having a number of retries, provide a seq of times to sleep for:
(loop [tries [10 10 100 1000]]
(let [res (try
(might-throw-exception)
(catch Exception e
(if tries
::retry
(throw e))))]
(if (#{::retry} res)
(do
(Thread/sleep (first tries))
(recur (next tries)))
res)))
And finally put it all into a macro if you want it to be less verbose:
(defmacro with-retries
[retries & body]
`(loop [retries# ~retries]
(let [res# (try ~#body
(catch Exception e#
(if retries#
'retry#
(throw e#))))]
(if (= 'retry# res#)
(do (Thread/sleep (first retries#))
(recur (next retries#)))
res#))))
(with-retries [10 10 100 1000]
(might-throw-exception))