为什么我们不能在Clojure中编写嵌套的简写函数?


11

今天,我尝试使用嵌套的简写函数来评估Clojure表达式,但它不允许我这样做。

表达式是:

(#(+ % (#(+ % (* % %)) %)) 5) ; sorry for the eye bleed

输出为:

IllegalStateException Nested #()s are not allowed  clojure.lang.LispReader$FnReader.invoke (LispReader.java:630)
...and a bunch of other garbage

2
我发现无法编写这样的代码对于clojure是一件好事。
西蒙·贝格

3
因为它会使您的眼睛流血。
迈克尔·肖

您不需要(#(+%1(#(+%2(*%3%4))%5))5)吗?
innova

Answers:


5

您会知道%属于内部函数。缺点是您将无法访问外部函数中的%。

请改用fn [x]语法。


1
所以?大多数时候,我不需要访问%外部fn,并且在您访问的时间,您可能会回退到(fn),对吗?
Zaz

10

这是完全任意的;解析器中有几行明确禁用了它。如果您对该行进行编辑,则可以嵌套嵌套的匿名函数,它们的行为与您期望的完全相同。

具体来说,https: //github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LispReader.java中的第634-635行

public static class FnReader extends AFn{
    public Object invoke(Object reader, Object lparen) {
        PushbackReader r = (PushbackReader) reader;
        if(ARG_ENV.deref() != null) // <-- line 634
            throw new IllegalStateException("Nested #()s are not allowed");
        // ...

您能否在解析器中标识该行,并证明重写的代码没有anon嵌套函数,并且从解析器中删除了该行的代码以及anon嵌套函数,它们的工作原理相同?

2
@MichaelT:你去。您就可以对其进行测试;这很容易做到,因为您可以在运行时将它们切换出。clojure解析器确实很容易被黑客入侵
amara 2013年

4
好吧,不是完全武断;除非Rick Hickey每天有一个随意的日子,否则一定有他将它放在那里的原因,而且您似乎不知道那是什么原因。咄。
罗伯特·哈维

哇,真是个发现!不错-+1。

此更改会导致嵌套方法的任何歧义解析吗?我很好奇fn [x]OP的代码重写将具有与经过修改的clojure版本相同的功能。此外,clojure代码的可移植性是否存在任何问题?

3

您可以具有(fn [params](body))排序的嵌套匿名函数。仅#语法不支持嵌套。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.