函数打印在clojure中有缺陷吗?

函数打印在clojure中有缺陷吗?,clojure,macros,eval,Clojure,Macros,Eval,我写了一个宏: (defmacro te [a b & c] `(print ~(a b c))) 跑 (te print 2 inc 4) 获取错误ClassCastException java.lang.Long无法强制转换为clojure.lang.IFn用户/eval8010(表单-init8519408737285198.clj:1) 我跑 (macroexpand-1 '(te print 2 3 4) ;=> (clojure.core/prin

我写了一个宏:

(defmacro te
  [a b & c]
  `(print
     ~(a b c)))

(te print 2 inc 4)
获取错误
ClassCastException java.lang.Long无法强制转换为clojure.lang.IFn用户/eval8010(表单-init8519408737285198.clj:1)

我跑

(macroexpand-1 '(te print 2 3 4)
;=> (clojure.core/print (3 4))
它的意思是
(打印2(34))
返回
(34)
?它的功能
print
有缺陷吗

我的clojure版本1.7.0,JVM版本1.8.0_65-b17


更新

好的,这个例子不容易被commit理解

就连我自己也在经营这家公司

(te print 2 inc 4)

user=> (te print 2 inc 4)
;=> 5nil

user=> (macroexpand-1 '(te print 2 inc 4))
;=> (clojure.core/print (inc 4))

它将打印
5
并返回
nil
,这意味着
(打印2(inc 4))
返回表单
(inc 4)

这与
打印
完全无关

它的意思是
(打印2(34))
返回
(34)

这不是它的意思,这是你问题的根源。它表示“使用第一个参数
2
调用函数
print
,第二个参数调用
(34)
”的值。表达式
(3 4)
没有有效值,因为它表示“使用参数
4
调用函数
3
”,这就是为什么会出现异常:3是一个长(数字),不能作为函数调用(在clojure内部,它不实现IFn函数接口)


顺便说一句,如果我了解您想要实现的目标(我可能错了),您的宏可以很容易地作为函数编写,这通常意味着您应该将其作为函数编写,因为函数更容易处理,并且与其他函数一起工作得更好。

请记住,宏的参数在执行宏时没有计算过 被调用

当您像这样调用宏时:

(te print 2 inc.4)

这些参数绑定到以下各项:

  • 答:
    打印
  • b:
    '2
  • c:
    ”(inc 4)
    (因为宏是可变的,所以超过前两个的任何参数都会被放入 进入
    c
    中的列表)
最终得到的表达式是:

`(print~('print'2'(inc 4)))

问题是:内部
打印
与函数不是一回事
clojure.core/print
。这是一个宏,所以它是一个未赋值的符号。你正在使用 在本例中,符号本身作为函数,而不是使用引用的函数 用符号来表示

Clojure中的每个符号都是在地图中查找自身的函数。 查找需要两个步骤 参数、键和默认值。在这种情况下,符号
打印
正在尝试查找 在2分钟内自动上升。由于2不是映射,它将返回默认值
(inc 4)

回想一下,unquote(
~
)表示计算表达式并替换结果 输入宏生成的代码

因此编译器计算:
('print'2'(inc4))
返回
(inc4)
,然后 将其替换为原始表达式

这就是你如何得到
(clojure.core/print(inc 4))

试试这个:

(macroexpand-1’(te blarg 2 inc.4))

你甚至可以得到完全相同的结果 尽管
blarg
不是Clojure中定义的变量

在你的另一个例子中,另一个答案非常正确。如果宏的第三个参数不是函数,则会出现另一个错误


老实说,我不确定你想完成什么,所以我不确定这是否真的回答了你的问题。但这就是为什么你看到了你所看到的。

为什么人们经常认为公共库/框架中存在未在相关组中报告的bug{相反,考虑这一点:表单<代码>(3 4)<代码>在Culjure中意味着什么?(在RePL上对宏的输出进行评估是无关的)。为什么会导致报告错误?为什么错误仍然存在(并且它会)。在用其他东西替换
print
之后?我知道,但我想你不明白我的问题的意思。在宏中,~(ab c)可以重新运行一个非零的值吗
a
是函数
print
它将返回一个表单
c
?我想你想问的是:因为
`(print inc~(2))
将获得表单
(打印3)
,为什么
(defmocro打印结果[ab]`(打印~(ab))
(macroexpand-1'(打印结果inc 2))
将获得
(打印零)
(a2(34)
实际上返回
(34)
,不过,
a
的值是符号
print