此补丁更改了与宏结合使用时元数据的行为。现在,元数据 &form 将与宏调用 sexpr 的元数据合并。这使用户可以在宏调用中为内部或外部形式类型注释,并获得更好的结果。过去,宏展开的元数据被按原样使用。这不允许如下所示的代码,不使用反射来工作
(.trim ^String (when true "hello "))
补丁: 2013-10-11_CLJ-865_Fix-With-Tests.diff
审核人: Timothy Baldridge
--------- 实施细节 ----------
正如在 http://groups.google.com/group/clojure/browse_thread/thread/2690cb6ca0e8beb8 中讨论的那样,当对表示宏的表达式进行类型注释时(例如,使用 (.length ^String (doto (identity "x") prn))),存在一个“惊喜因素”。在这里,doto 宏丢弃了 &form 上的元数据,导致反射查找。这会影响尽管函数调用表示的表达式可以进行类型注释,但表示宏的总括性表达式不能。doto 宏可以重写以尊重其 &form 元数据,但这对于现有的每一个宏来说都是乏味且容易出错的。相反,我建议对编译器进行更改,以便使宏展开自动保留元数据。
附加的第一个补丁为我在提案中提出的行为添加了一个测试:此测试失败。应用第二个补丁后,测试通过。
在接受我的补丁之前,有几个要点值得进一步考虑
- 我不确定我是否正确地格式化了Java代码。我的编辑器没有正确配置以自动获得clojure/core样式。
- 我的解决方案是 took &form 元数据,删除 :line/:file 键,然后与返回的元数据合并,&form 优先。我不确定这是否是所有情况下的正确方法,尽管它对 :tag 元数据有效。
- 我通过更改编译器实现这一点,这相当重。应该可能通过调整defmacro进行更改,而不希望更改编译器。然而,我认为这需要更多的工作,并且更难测试(例如,多参数使事情变得复杂)。似乎更优雅的做法是将宏展开视为黑盒,然后对结果进行元数据调整,而不是修改真实的defmacro代码。
- 如果宏展开为的不是IObj,例如整数,那么我的补丁默默地丢弃了调用者的元数据。抛出异常会更好吗?