Reputation: 32284
I wrote a small anonymous function to be used with a map
call. The function returns a vector containing a column name and column value from a SQL result set query.
Here is the function (input is the column name):
(fn [name] [(keyword name) (.getObject resultset name)])
This works fine, however when I tried to use a "simplified" version of the anonymous function, I got an error:
#([(keyword %) (.getObject resultset %)])
java.lang.IllegalArgumentException: Wrong number of args (0) passed to: PersistentVector
Here is the map
call:
(into {} (map (fn [name] [(keyword name) (.getObject resultset name)]) column-names))
Is it possible to use the simplified syntax for this function? If so, how?
Thanks.
Upvotes: 25
Views: 7331
Reputation: 1069
There are already good answers. But no answer explains what is going on.
In Clojure you can define anonymous function literals with #(...)
. Nothing else can be used to define anonymous function literals. This happens before the form reaches the evaluation. This is a so called reader macro. The reader really must see this #(
. When seeing it, the reader immediatelly replaces it by something like (fn [args] (...)
. This is explicitly defined here.
That means, you can only ever use anonymous function literals for things, that have exactly this format with the parenthesis. If all you want to do is returning something without calling anything, anonymous function literals do not work. The following examples cannt be written with anonymous function literals, because they need no parenthesis.
(fn [x] x)
(fn [x] [x])
(fn [] 7)
(fn [] [7])
As you can see in the other answers there are good workarounds, that enable you to write something, that needs the parenthesis.
On the one hand it would be interesting to write a user macro #[...]
. But on the other hand, as you saw, in your case this is not really needed. There are good solutions for your question. See also this question about the topic.
Note that when working with EDN data, there is principally a solution. But most likely this does not answer your question, because you probably don't want to use the EDN reader.
Upvotes: 0
Reputation: 3357
Yeah, Clojure should really support a #[...] construct, just for this case.
I would recommend the following as the best alternative:
#(vector (keyword %) (.getObject resultset %))
Upvotes: 5
Reputation: 87119
You need to use vector function to do this:
#(vector (keyword %) (.getObject resultset %))
P.S. there are also functions for maps, sets, etc.
Upvotes: 27
Reputation: 106351
Your problem is that the simple syntax is trying to evaluate the vector as a function call.
You can insert an "identity" function to make it work, as this is just a simple function that will return the vector unchanged:
#(identity [(keyword %) (.getObject resultset %)])
Upvotes: 29