我目前正在尝试建立一个简单的函数,该函数读取一个整数列表并按如下所示返回每个整数的平方:
(defn square-seq
[s]
(if (string? s)
(s = nil)
(map #(* % %) s)))
但是,我希望代码能够处理字符串输入,并将它们默认设置为数值以防止ClassCastException。就像我这样做
(square-seq ["Hello" 2 3])
然后返回值为:
(1 4 9) or (nil)
不知道我是想得太多还是只是太笨了,但我不知道如何让它在我的一生中发挥作用,任何帮助将不胜感激!
答案 0 :(得分:0)
您正在检查顶级字符串,因此您极有可能永远不会到达该分支。您必须检查它实际触发错误的位置(在anon-fn内部)。
所以我先写一个函数,做一个“安全平方”,您的async function transformUser(userId, loaders) {
const user = await loaders.userLoader.load(userId.toString());
return {
...user._doc,
createdOrchestras: await Promise.all(
user._doc.createdOrchestras.map(orchestra =>
transformOrchestra(orchestra, loaders)
)
)
}
}
async function transformOrchestra(orchestraId, loaders) {
const orchestra = await loaders.orchestraLoader.load(orchestraId.toString());
return {
...orchestra._doc,
owner: transformUser(orchestra._doc.owner, loaders)
}
}
module.exports = {
transformUser,
transformOrchestra
}
可以调用它。
square-seq
答案 1 :(得分:0)
作为练习,我会提出如下实用函数:
(letfn [(single-or-all [arg & args] (if (seq args)
(vec (cons arg args))
arg))]
(defn mapper [f & {:keys [guard guard-failed]
:or {guard (constantly true)
guard-failed single-or-all}}]
(fn [& items] (if (apply guard items)
(apply f items)
(apply guard-failed items)))))
这里的mapper
工厂函数会生成保护输入的函数,并在保护失败的情况下导致回退函数调用:
;; default usage:
user> (map (mapper #(* % %)) [1 2 3])
;;=> (1 4 9)
;; guard with default result:
user> (map (mapper #(* % %) :guard number?) [1 2 "aaa" 3])
;;=> (1 4 "aaa" 9)
;; guard with custom result:
user> (map (mapper #(* % %)
:guard number?
:guard-failed (constantly -1)) [1 2 "aaa" 3])
;;=> (1 4 -1 9)
;; multiple collections mapping with guards:
user> (map (mapper +
:guard #(every? number? %&))
[1 2 "aaa" 3]
[10 "zzz" 20 30])
;;=> (11 [2 "zzz"] ["aaa" 20] 33)
user> (map (mapper +
:guard #(every? number? %&)
:guard-failed (partial vector :guard/failed))
[1 2 "aaa" 3]
[10 "zzz" 20 30])
;;=> (11 [:guard/failed 2 "zzz"] [:guard/failed "aaa" 20] 33)
user> (map (mapper +
:guard #(every? number? %&)
:guard-failed #(apply + (filter number? %&)))
[1 2 "aaa" 3]
[10 "zzz" 20 30]
[100 "x" 200 300])
;;=> (111 2 220 333)
答案 2 :(得分:0)
好像是一个简单的try/catch
的场合:
(defn square
[x]
(try
(* x x)
(catch Exception ex
:error)))
和用法:
(mapv square ["hello" 2 3]) => [:error 4 9]
尽管我会争辩说呼叫者应该有try/catch
语句,因为当存在非数字时,只有呼叫者能够(也许!)做一些聪明的事情。
答案 3 :(得分:0)
我将尝试回答“防止运行时错误” 部分。基本思想是用异常处理程序包装目标函数,以便可以(使用另一个函数)处理运行时错误。使用通用处理程序,您可以轻松地将此机制应用于您使用的任何目标函数...
(defn square-seq
[xs]
;; here safe-fn is a high order function to make * safe
;; by attaching an exception handler to it (which always return 1)
(map (safe-fn * (constantly 1)) xs xs))
(square-seq ["Hello" 2 3])
;; => (1 4 9)
(defn half-seq
[xs]
;; here we make / safe and also provide a different handler
(map (safe-fn / (constantly 99)) xs (repeat 2)))
(half-seq ["Hello" 2 3])
;; => (99 1 3/2)
(defn triple-seq
[xs]
;; yet another handler
(apply map (safe-fn * (constantly 3)) (repeat 3 xs)))
(triple-seq ["Hello" 2 3])
;; => (3 8 27)
safe-fn
可以很容易地实现为:
(defn safe-fn [f ex-handler]
(fn [& args]
(try
(apply f args)
(catch Throwable t
(ex-handler t args)))))