Thanks, I realize my example is a bit of a corner case, and feels a little artificial:) It came after some narrowing down a larger problem
Another thing that appeared curious to me, is that Clojure apparently counts unique %'s inside the #() definition to determine arity of the macro. But does this mean that macros with no arguments should be legal? How about this: (#(true)), is this not calling a function that has no arguments and returns true? But it still gives same exception <CompilerException java.lang.ClassCastException: java.lang.Boolean cannot be cast to clojure.lang.IFn (NO_SOURCE_FILE:0)> I come from Scala experience, where it is easy to define a quick lambda function returning a constant or another simple expression, e.g. "=> true" is a function with no args and returning true. Things like that are sometimes useful to pass into higher-order functions expecting a function, not a constant. I guess I should forgo the macro and go directly with (fn [] true) I think all of this confusion could have been avoided if the compiler did a better error message, e.g. actually citing the definition of #() and what it expanded into? Would improve usability. Even macroexpand does not provide any useful info in this case... Certainly macros are not for the fainthearted anyway, but all literature seems to go into #() really fast, so it will be stumbled upon by novices Julian On Sep 6, 12:44 pm, Laurent PETIT <laurent.pe...@gmail.com> wrote: > 2011/9/4 julianrz <julia...@yahoo.com> > > > Hello All, > > I am new to Clojure. Surprised why this code does not work: > > > user=> (filter #(%) [1 2 3]) > > ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn > > > Here my intent behind #(%) is to define a lambda function returning > > its argument. Since Clojure defines truth on any type, it should be > > acceptable as filter function, and the result should be the original > > array > > > Some narrowing down. What's #(%) really good for? > > Hello, > > #(%) is a macro which expands to (fn* [p1#] (p1#)) > > #(%) could only be 'useful' if % is a callable without arguments. > > What you seem to be after is the builtin function named identity : identity > returns its argument : > > Clojure> (filter identity [1 true false nil]) > (1 true) > Clojure> > > HTH, > > -- > Laurent > > > > > user=> #(%) > > #<user$eval48$fn__49 user$eval48$fn__49@5e2c17f7> > > > so it is a function > > > user=> (#(%)) > > ArityException Wrong number of args (0) passed to: user$eval26$fn > > > Ok, here not enough arguments supplied, fair enough. Let's fix that: > > user=> (#(%) 1) > > ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn > > > Same problem as the first example. So Clojure understands this is a > > function, knows it takes some arguments, but cannot call it? What's > > wrong? The following works: > > > (user=> (filter (fn [a] a) [1 2 3]) > > (1 2 3) > > > So apparently it has something to do with the fact that #() is > > shorthand. So in my case, it produces a function which cannot be > > used... In fact, it seems to just yield the constant, not a function. > > Ask me, it should work (auto-wrap the constant in a function) or the > > expression should be illegal. I think it deserves better > > diagnostics... > > > Also, in Practical Clojure book, it says: "The shothand function form > > #(* %1 %2) is actually identical to the longer form (fn [x y] (* x y)) > > before it is even seen by the compiler." If you literally apply this > > rule, you will get > > > ((fn[x] (1)) 1) > > > which throws same exception, not surprisingly, since it tries to > > evaluate 1 as a fucntion. What it should have done is transform the > > expression into > > > ((fn[x] 1) 1) > > > which works fine... Special-case it? > > > What do you think? > > > Julian > > > -- > > You received this message because you are subscribed to the Google > > Groups "Clojure" group. > > To post to this group, send email to clojure@googlegroups.com > > Note that posts from new members are moderated - please be patient with > > your first post. > > To unsubscribe from this group, send email to > > clojure+unsubscr...@googlegroups.com > > For more options, visit this group at > >http://groups.google.com/group/clojure?hl=en -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en