15

Are nested anonymous function legal or not? I wrote the following for the problem #107 of 4clojure:

(fn [n] #(reduce * (repeat n %)))

which passed all the 3 tests, however when i try it with the test 3 in repl i get an IllegalStateException saying that nested #()s are not allowed:

IllegalStateException Nested #()s are not allowed  
clojure.lang.LispReader$FnReader.invoke (LispReader.java:628)

CompilerException java.lang.RuntimeException: Unable to resolve symbol: n 
in this context, compiling:(NO_SOURCE_PATH:1:44) 

RuntimeException Unmatched delimiter: )  

clojure.lang.Util.runtimeException (Util.java:221)

RuntimeException Unmatched delimiter: )  

clojure.lang.Util.runtimeException (Util.java:221)

CompilerException java.lang.RuntimeException: Unable to resolve symbol: % 
in this context, compiling:(NO_SOURCE_PATH:0:0) 

RuntimeException Unmatched delimiter: )  

clojure.lang.Util.runtimeException (Util.java:221)

RuntimeException Unmatched delimiter: )  

clojure.lang.Util.runtimeException (Util.java:221)

RuntimeException Unmatched delimiter: )  

clojure.lang.Util.runtimeException (Util.java:221)

RuntimeException Unmatched delimiter: )  

clojure.lang.Util.runtimeException (Util.java:221)

Why this cant be passed on repl but on 4clojure?

1 Answer 1

19

Nested anonymous functions are perfectly OK. But you can't nest the #() reader macro, because then it's not well defined - we can't know if by %1 the programmer meant the first argument to the outer function literal or the first argument to the inner function literal.

You'll need to type the inner function out 'longhand' (using fn) if you want to evaluate the entire test form.

(fn [n]
  (fn [m] 
    (reduce * (repeat n m))))

It working on 4Clojure must likely be because they evaluate the form you provide before inserting it into the test forms. As such, the #() macro has already been expanded (to a fn*) when the test form is evaluated.

Sign up to request clarification or add additional context in comments.

4 Comments

i was wondering, because my version with the #() reader macro also passed the test on 4clojure, but not in my repl. Thanks anyway for your explanation
Ah, I misunderstood your question a bit then. In that case the #() must already have been macro-expanded when it's inserted into the test forms
DOC; in case anyone looks for it: Ctrl-F for: #() forms cannot be nested in clj-doc
because they evaluate the form you provide - actually we just read the form you provide first. The #() syntax is expanded by the reader, not by evaluation, so this is sufficient. Good point, though - I never noticed that this means there are solutions valid in 4clojure that don't work locally.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.