clojure - clojure defn 参数不允许使用 ^char 类型提示

标签 clojure

观察以下 repl session :

user=> (set! *warn-on-reflection* true)
true

user=> (defn blah [s] (for [c s] (if (Character/isDigit c) true false)))
Reflection warning, NO_SOURCE_PATH:1:31 - call to isDigit can't be resolved.
Reflection warning, NO_SOURCE_PATH:1:31 - call to isDigit can't be resolved.
#'user/blah

user=> (blah "abc123abc")
(false false false true true true false false false)

user=> (defn blah [s] (for [^char c s] (if (Character/isDigit c) true false)))
#'user/blah

user=> (blah "abc123abc")
(false false false true true true false false false)

因此我们使用了 ^char 的类型提示来摆脱反射 - 太棒了。现在在函数参数中尝试同样的事情:

user=> (defn blah-c [c] (if (Character/isDigit c) true false))
Reflection warning, NO_SOURCE_PATH:1:22 - call to isDigit can't be resolved.
#'user/blah-c

user=> (defn blah-c [^char c] (if (Character/isDigit c) true false))
CompilerException java.lang.IllegalArgumentException: Only long and double primitives are supported, compiling:(NO_SOURCE_PATH:1:1) 

user=> (defn blah-c [^Character c] (if (Character/isDigit c) true false))
#'user/blah-c
user=> (blah-c \1)
true
user=> (blah-c \a)
false

我了解 Clojure only supports long or double type hints for numeric primitives ,并且 Java char 是一种数字数据类型 - 无需解释。但上面似乎不一致 - 在 for 内的第一个函数中允许类型提示 ^char,但在 blah-c 的函数签名中不允许>,我必须在其中指定Character。这是什么原因(即从编译器实现的角度来看)?

最佳答案

在类型提示中for您正在标记的表达式 c作为char作为对编译器的提示。当编译器为 isDigit 发出(静态)方法时然后它知道您想要接受 char 的版本(可能与 int 版本相反)。字节码被发送到实现 O 的函数对象中(单个 Object 参数)IFn 的版本接口(interface)(默认情况下所有参数都已装箱)。

在另一种情况下,blah-c ,字节码需要发送到实现不存在的 C 的函数对象。 (例如,对于 char )IFn 的版本界面。每个原语都可以有接口(interface)吗?当然可以,但是没有。对于每种可能的组合?由于组合爆炸,不可行。

你可能会说,好吧,为什么不直接发出 blah-cO界面?这将违背函数参数上类型提示的要点,即避免装箱/拆箱,因为随后必须对字符基元进行装箱才能进行调用。函数参数的类型提示的目的不仅仅是为了避免反射。如果你想在这里避免反射,那么你不会标记函数参数,而是将其强制转换为 charlet在创建 isDigit 之前阻止打电话。

clojure.lang.IFn中的注释,枚举接口(interface)(当前)仅限于任意数量的对象(盒装类型)以及最多四种 double 的组合。和long类型。 doublelong提供版本是为了优化,以避免在基元上编写性能关键代码时装箱/拆箱,并且应该足以满足大多数用途。

关于clojure - clojure defn 参数不允许使用 ^char 类型提示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17323769/

相关文章:

functional-programming - 返回前 X 位设置的数字

serialization - 在 Clojure 中吐出和吞咽一个向量

clojure - 如何在 Clojure 中测试空向量

clojure - 热修复 "WARNING: any? already refers to: #' clojure.core/any?在命名空间 : leiningen. midje 中,被替换为:#'leiningen.midje/any?"

clojure - 生成长度为 N 的相同项的向量

clojure - 如何为试剂组件编写装饰器

clojure - 是否可以将 clojure 向量分解为最后两项和其余项?

function - 设计师为什么要在clojure里做vector、map、set函数?

Clojure 中的 Emacs 自动缩进 - 它像 CL 吗?

clojure - 如何将字符串包装在输入流中?