我想创建一个函数,我可以传递一个函数映射并将这些函数应用到另一个映射 - 将其视为强制将字符串映射到任意类型。 (我喜欢做更高级别的事情,比如fmap,但一次一步,对吗?)
因此,我认为我需要做一些像
这样的事情user=> (apply Long. "1")
但是当我尝试时,我得到了这个:
CompilerException java.lang.ClassNotFoundException: Long., compiling:(/private/var/folders/c9/5yl3m9pn0rjdnvqlp5v4fzhr0000gn/T/form-init8437802472507251220.clj:1:1)
我当然可以通过这种方式找到课程:
user=> (Long. "1")
1
如果我这样做
user=> (apply #(Long. %1) "1")
我看到了
IllegalArgumentException No matching ctor found for class java.lang.Long clojure.lang.Reflector.invokeConstructor (Reflector.java:183)
这令人困惑,因为我刚才使用了构造函数。无论如何,我想我做到了。它甚至找到了正确的类,而不是类的构造函数。
这也失败了,不同的是:
user=> (apply #(new Long. %1) "1")
CompilerException java.lang.ClassNotFoundException: Long., compiling:(/private/var/folders/c9/5yl3m9pn0rjdnvqlp5v4fzhr0000gn/T/form-init8437802472507251220.clj:1:9)
我可以找不到java.lang.Long,这很有趣:
user=> (apply #(new java.lang.Long. %1) "1")
CompilerException java.lang.ClassNotFoundException: java.lang.Long., compiling:(/private/var/folders/c9/5yl3m9pn0rjdnvqlp5v4fzhr0000gn/T/form-init8437802472507251220.clj:1:9)
但这有效:
user=> (defn l [x] (Long. x))
#'user/l
user=> (apply l ["1"])
1
我可以用这种方式编写我的代码,虽然看起来有点......关闭?
无论如何,这里发生了什么?为什么这有意义?
答案 0 :(得分:1)
Java functions, including constructors, are not legal Clojure functions and cannot be passed directly to higher-order-functions like apply
unless they are wrapped inside a Clojure function.
Also, note that apply
expects an collection of args, as it "unwraps" them from the array. This works for a vector with one string:
(Long. "1") -> 1
(apply #(Long. %) ["1"] ) -> 1
But what you really probably want is mapv
or map
:
(mapv #(Long. %) ["1" "2" "3"] ) -> [1 2 3]
I'll let you figure out whats wrong with these failing cases:
; failing cases
; (apply Long. ["1"] )
; (apply #(Long. %) ["1" "2" "3"] )
; (apply #(Long. %) "1" "2" ["3"] )