此补丁更改了与宏相关联时元数据的行为。现在元数据 &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 元数据,但为现有的每个宏这样做将非常繁琐且容易出错。因此,我建议更改编译器,以自动保留宏展开的元数据。
附加的第一个补丁添加了对建议行为的测试:此测试失败。应用第二个补丁后,测试通过。
在接收我的补丁之前,有几点 worth 进一步考虑:
- 我不确定我是否正确地格式化了 Java 代码。我的编辑器没有正确配置以自动获取 clojure/core 风格。
- 我的解决方案是取出 &form 元数据,删除 :line/:file 关键字,然后将它与其他返回的元数据合并,其中 &form 优先级更高。虽然这个方法适用于 :tag 元数据,但我不确定它是否适用于所有情况。
- 我通过更改编译器实现了这一目标,这在某种程度上是相当复杂的。如果不需要更改编译器,则可能可以通过调整 defmacro 来实现,但这将需要大量工作,并且测试更困难(例如,多态调用会使情况复杂化)。似乎将宏展开视为一个黑盒,然后再对其进行元数据调整要好一些,而不是修改它们的实际 defmacro 代码。
- 如果宏展开的内容不是 IObj,如 Integer,那么我的补丁会静默地丢弃调用者的元数据。抛出异常是否更好?