我想创建一个函数,它可以传递函数映射并将这些函数应用于另一个映射——可以将其视为将字符串映射强制转换为任意类型。(我想做一些更高级的东西,比如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。很长,很有趣:
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
我可以这样写我的代码,虽然它看起来有点…假吗?
不管怎样,这是怎么回事?为什么说得通呢?Java函数,包括构造函数,不是合法的Clojure函数,不能直接传递给像apply
这样的高阶函数,除非它们被包装在Clojure函数中。
另外,注意apply
需要一个参数集合,因为它从数组中"解包裹"它们。这适用于只有一个字符串的vector:
(Long. "1") -> 1
(apply #(Long. %) ["1"] ) -> 1
但是你真正想要的可能是mapv
或map
:
(mapv #(Long. %) ["1" "2" "3"] ) -> [1 2 3]
我会让你找出这些失败案例的问题所在:
; failing cases
; (apply Long. ["1"] )
; (apply #(Long. %) ["1" "2" "3"] )
; (apply #(Long. %) "1" "2" ["3"] )