13

我对clojureinstance?函数有点困惑。接受一个论点似乎很高兴。所以

(instance? String) 

工作正常,但总是返回 false。

我在这里错过了什么吗?这两天我做了两次,两次都花了我相当长的时间来调试(是的,我同意,犯一次错误可能被认为是不幸,但两次看起来像粗心)。

为什么它不会因为arity错误而中断?

稍后添加的注释:从 Clojure 1.6 开始,此问题已得到修复!

http://dev.clojure.org/jira/browse/CLJ-1171

4

4 回答 4

8

有趣......即使在instance?中定义core.clj,似乎也有内置的特殊处理clojure.lang.Compiler形式(instance?)

Compiler.java,第 3498 行

    if(fexpr instanceof VarExpr && ((VarExpr)fexpr).var.equals(INSTANCE))
        {
        if(RT.second(form) instanceof Symbol)
            {
            Class c = HostExpr.maybeClass(RT.second(form),false);
            if(c != null)
                return new InstanceOfExpr(c, analyze(context, RT.third(form)));
            }
        }

我将其解释为,当您编译/评估(instance?)表单时,core.clj忽略中定义的函数以支持硬连线行为,该行为确实将缺少的第二个参数解释为nil. 我猜这是出于性能原因,作为一种内联。

显然,这种特殊处理仅适用于某些情况(而且我对编译器不够熟悉,不知道它们是什么)。正如 Ankur 的回答所示,有一些调用方法instance?会导致调用定义的函数core.clj

于 2012-11-01T17:13:34.453 回答
3

我认为这是一个错误。如果您定义一个新版本的实例?,例如

(def
^{:arglists '([^Class c x])
  :doc "Evaluates x and tests if it is an instance of the class
        c. Returns true or false"
  :added "1.0"}
foo? (fn foo? [^Class c x] (. c (isInstance x))))

你会得到预期的异常

user=> (foo? String "bar")
true
user=> (foo? String 1)
false
user=> (foo? String)
ArityException Wrong number of args (1) passed to: user$foo-QMARK-  clojure.lang.AFn.throwArity (AFn.java:437)
于 2012-11-01T15:48:43.867 回答
2

如果您查看instance?代码,您将看到调用isInstance的方法:Class

(def
    ^{:arglists '([^Class c x])
      :doc "Evaluates x and tests if it is an instance of the class
            c. Returns true or false"
      :added "1.0"}
    instance? (fn instance? [^Class c x] (. c (isInstance x))))

看起来像在幕后,nil(或falsex在传递给时被视为参数的默认值,isInstance并且返回false

于 2012-11-01T12:43:12.800 回答
2

嗯....有趣...以下所有调用都失败了(应该是这样的):

user=> (.invoke instance? String)
ArityException Wrong number of args (1) passed to: core$instance-QMARK-  clojure.lang.AFn.throwArity (AFn.java:437)

user=> (instance? (type ""))
ArityException Wrong number of args (1) passed to: core$instance-QMARK-  clojure.lang.AFn.throwArity (AFn.java:437)

user=> (apply instance? String [])
ArityException Wrong number of args (1) passed to: core$instance-QMARK-  clojure.lang.AFn.throwArity (AFn.java:437)

user=> (#'instance? Long)
ArityException Wrong number of args (1) passed to: core$instance-QMARK-  clojure.lang.AFn.throwArity (AFn.java:437)

创建“实例?”的新实例的事件 函数对象按预期工作:

user=> (def a (.newInstance (aget (.getConstructors (type instance?)) 0) (into-array [])))
#'user/a
user=> (a String)
ArityException Wrong number of args (1) passed to: core$instance-QMARK-  clojure.lang.AFn.throwArity (AFn.java:437)
user=> (a String "")
true
于 2012-11-01T15:58:28.363 回答