If statement 防止在使用错误类型时出现运行时错误

If statement 防止在使用错误类型时出现运行时错误,if-statement,error-handling,clojure,If Statement,Error Handling,Clojure,我目前正在尝试设置一个简单的函数,该函数读取整数列表并返回每个整数的平方,如下所示: (defn square-seq [s] (if (string? s) (s = nil) (map #(* % %) s))) 但是,我希望代码能够处理字符串输入,并将它们默认为一个数值,以防止出现ClassCastException。比如说,如果我这样做的话 (square-seq ["Hello" 2 3]) 那么返回值是: (1 4 9) or (nil) 我不知道我是不

我目前正在尝试设置一个简单的函数,该函数读取整数列表并返回每个整数的平方,如下所示:

(defn square-seq
  [s]
  (if (string? s)
    (s = nil)
    (map #(* % %) s)))
但是,我希望代码能够处理字符串输入,并将它们默认为一个数值,以防止出现ClassCastException。比如说,如果我这样做的话

(square-seq ["Hello" 2 3])
那么返回值是:

(1 4 9) or (nil)

我不知道我是不是想得太多了,或者只是太多了,但我不知道如何让它在我的生活中发挥作用,任何帮助都将不胜感激

您正在检查顶层的字符串,因此很可能永远不会碰到该分支。您必须检查它实际触发错误的位置(在anon fn内)

所以我先写一个函数,它做“安全平方”,你的
square-seq
可以调用它

(defn square
  [x]
  (if (string? x)
    x
    (* x x)))

(defn square-seq
  [xs]
  (map square xs))

(square-seq ["Hello" 42])
; ⇒ ("Hello" 1764)

作为练习,我建议使用如下效用函数:

(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)

似乎是一个简单的尝试的机会:

(defn square
  [x]
  (try
    (* x x)
    (catch Exception ex
      :error)))
在使用中:

(mapv square ["hello" 2 3]) => [:error 4 9]

尽管我认为调用者应该有
try/catch
语句,因为只有调用者能够(可能!)在出现非数字时执行智能操作。

我将尝试回答中的“防止运行时错误”部分。基本思想是使用异常处理程序包装目标函数,以便可以处理运行时错误(使用另一个函数)。使用泛型处理程序,您可以轻松地将此机制应用于您使用的任何目标函数

(定义方形顺序)
[xs]
这里safe fn是使*安全的高阶函数
;通过将异常处理程序附加到它(总是返回1)
(地图(安全fn*(持续1))xs xs)
(方形序号[“你好”23])
;; => (1 4 9)
(除下半部分)
[xs]
;在这里,我们制造/安全,并提供不同的处理程序
(图(安全fn/(持续99))xs(重复2)))
(半序列[“你好”23])
;; => (99 1 3/2)
(定义三重序列)
[xs]
还有一个处理者
(应用map(安全fn*(持续3))(重复3次X)))
(三重序列[“你好”23])
;; => (3 8 27)
安全fn
可以轻松实现为:

(defn-safe-fn[f-ex-handler]
(fn[&args]
(试试看
(应用f参数)
(可丢弃的捕获物)
(前处理程序t参数(()()))

您正在使用参数调用
s
=nil
在那里
(s=nil)
非常出色正是我在寻找的,试图了解函数式风格需要时间。谢谢你的快速回复!我很想用
(if(string?x)…)
替换
(if不是(number?x)…)
,避免出现
x
是字符、向量、函数和c-以及字符串的例外情况。不要认为这是尝试/捕获的好时机。op的问题似乎更多地是关于映射时特定值的特殊处理,而不是处理异常。因为事实上这不是一个例外,而是业务逻辑。而且
(try(可能抛出函数x)…
将是一片混乱。