如何创建一个忽略任何参数并始终抛出异常的函数?

时间:2016-05-03 14:03:23

标签: clojure

根据{{​​1}}的Clojure docs

(constantly (throw (Exception. "Don't call me")))是我期望的。

  

constantly

     

返回一个接受任意数量参数并返回x的函数。

但是当我尝试不断创建一个总是抛出的模拟函数时,会立即抛出异常,我试图定义函数。 (constantly x)是否应该立即评估它的身体,并缓存结果?我是否遇到了相当于C的可怕的未定义行为(在这种情况下,"一旦你依赖副作用,所有的赌注都会关闭")

constantly

在测试中创建模拟回调函数的惯用方法是什么,以便在调用时抛出错误?

2 个答案:

答案 0 :(得分:6)

constantly是一个函数;它评估其参数,然后返回一个将返回该评估结果的函数。如果你想编写一个忽略其所有参数并在每次调用时计算某个表达式的函数,你可以这样做:

(fn [& _] (throw (Exception. "Don't call me")))

示例:

((fn [& _] (throw (Exception. "Don't call me"))) :foo :bar)
;=> java.lang.Exception: Don't call me

您还可以编写一个宏来创建忽略其参数的函数:

(defmacro ignore-args [& exprs]
  `(fn ~'[& _] ~@exprs))

示例:

((ignore-args (throw (Exception. "Don't call me"))) :foo :bar)
;=> java.lang.Exception: Don't call me

我不完全确定这样的宏有多么有用,因为在任何形式的描述性名称(ignore-args,在这种情况下),输入所需的时间比{{1并没有真正传达更多的语义含义。

答案 1 :(得分:1)

如果您只想要一个始终抛出异常的函数,您可以这样做:

(defn blowup [& args] (throw (Exception. "I just blew up")))

如果您正在寻找一种方法来按需提供,请尝试这样做:

(defn explosives-factory [e] (fn [& args] (throw e)))

你可以在这里看到它:

user=> (defn explosives-factory [e] (fn [&args] (throw e)))
#'user/explosives-factory
user=> (def blowup (explosives-factory (Exception. "Boom!")))
#'user/blowup
user=> (blowup 123)

Exception Boom! sun.reflect.NativeConstructorAccessorImpl.newInstance0 (NativeConstructorAccessorImpl.java:-2)