首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >闭包中的不一致性:宏和IllegalArgumentException中的函数

闭包中的不一致性:宏和IllegalArgumentException中的函数
EN

Stack Overflow用户
提问于 2013-10-17 12:53:38
回答 2查看 662关注 0票数 11

以下两个在宏中使用函数的示例将导致计算结果没有错误。

代码语言:javascript
代码运行次数:0
运行
复制
(defmacro works []
  (let [f (fn [] 1)]
    `(~f)))
(works)
;; => 1

(defn my-nullary-fn []
  (fn [] 2))
(defmacro also-works []
  (let [f (my-nullary-fn)]
    `(~f)))
(also-works)
;; => 2

然而,

代码语言:javascript
代码运行次数:0
运行
复制
(defmacro does-not-work []
  (let [f (constantly 3)]
    `(~f)))
(does-not-work)

抛出

代码语言:javascript
代码运行次数:0
运行
复制
java.lang.IllegalArgumentException: No matching ctor found
for class clojure.core$constantly$fn__4051 

同样的,

代码语言:javascript
代码运行次数:0
运行
复制
(defn my-unary-fn [x]
  (fn [] x))
(defmacro also-does-not-work []
  (let [f (my-unary-fn 4)]
    `(~f)))
(also-does-not-work)

抛出

代码语言:javascript
代码运行次数:0
运行
复制
java.lang.IllegalArgumentException No matching ctor found
for class user$my_other_fn$fn__12802

可能是什么原因?fnmy-nullary-fnconstantlymy-unary-fn返回的函数对象之间是否有区别?

我正在运行Clojure 1.5.1。

CLJ-946可能是相关的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-10-18 14:46:48

看看clojure.lang.Compiler.ObjExpr#emitValue()。任何直接出现在代码中的实例对象(或在宏展开结果中生成的代码)都必须是:

  • 类型编译器知道如何实例化或发出对;或
  • 为它们的类型定义print-dup,在这种情况下编译器通过读取器发出对象实例化。

函数对象确实有一个print-dup实现,但它构造的读- version只调用函数类构造函数的0参数版本:

代码语言:javascript
代码运行次数:0
运行
复制
(print-dup (fn [] 1) *out*)
;; #=(user$eval24491$fn__24492. )
(let [x 1] (print-dup (fn [] x) *out*))
;; #=(user$eval24497$fn__24498. )

Clojure闭包是通过函数类实现的,函数类接受它们的闭包变量值作为构造函数参数。因此:

代码语言:javascript
代码运行次数:0
运行
复制
(let [f (fn [] 1)] (eval `(~f)))
;; 1
(let [x 1, f (fn [] x)] (eval `(~f)))
;; IllegalArgumentException No matching ctor found ...

所以现在您知道了,并且知道了为什么要避免将函数对象直接插入到生成的代码中,即使它“工作”。

票数 7
EN

Stack Overflow用户

发布于 2013-10-17 14:56:35

请参阅此示例,该示例也会引发异常:

代码语言:javascript
代码运行次数:0
运行
复制
(defmacro does-also-not-work []
  (let [x 4
        f (fn [] x)]
    `(~f)))

constantly的结果一样,但与前两个示例不同的是,这里的f是一个闭包。显然,在宏扩展期间创建的闭包不会持续.

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19427303

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档