Anonymous function shorthand
There's something I don't understand about anonymous functions using the short notation #(..)
The following works:
REPL> ((fn [s] s) "Eh")
"Eh"
But this doesn't:
REPL> (#(%) "Eh")
This works:
REPL> (#(str %) "Eh")
"Eh"
What I don't understand is why (#(%) "Eh") doesn't work and at the same time I don't need to use str in ((fn [s] s) "Eh")
They're both anonymous functions and they both take, here, one parameter. Why does the shorthand notation need a function while the other notation doesn't?
#(...)
is shorthand for
(fn [arg1 arg2 ...] (...))
(where the number of argN depends on how many %N you have in the body). So when you write:
#(%)
it's translated to:
(fn [arg1] (arg1))
Notice that this is different from your first anonymous function, which is like:
(fn [arg1] arg1)
Your version returns arg1 as a value, the version that comes from expanding the shorthand tries to call it as a function. You get an error because a string is not a valid function.
Since the shorthand supplies a set of parentheses around the body, it can only be used to execute a single function call or special form.
As the other answers have already very nicely pointed out, the #(%)
you posted actually expands to something like (fn [arg1] (arg1))
, which is not at all the same as (fn [arg1] arg1)
.
@John Flatness pointed out that you can just use identity
, but if you're looking for a way to write identity
using the #(...)
dispatch macro, you can do it like this:
#(-> %)
By combining the #(...)
dispatch macro with the ->
threading macro it gets expanded to something like (fn [arg1] (-> arg1))
, which expands again to (fn [arg1] arg1)
, which is just want you wanted. I also find the ->
and #(...)
macro combo helpful for writing simple functions that return vectors, e.g.:
#(-> [%2 %1])
When you use #(...)
, you can imagine you're instead writing (fn [args] (...))
, including the parentheses you started right after the pound.
So, your non-working example converts to:
((fn [s] (s)) "Eh")
which obviously doesn't work because the you're trying to call the string "Eh". Your example with str
works because now your function is (str s)
instead of (s)
. (identity s)
would be the closer analogue to your first example, since it won't coerce to str.
It makes sense if you think about it, since other than this totally minimal example, every anonymous function is going to call something, so it'd be a little foolish to require another nested set of parens to actually make a call.