4

I'm trying to learn Clojure, and am blocked up around the literal function syntax. I can't figure out what the literal function equivalent of (defn fourteen [] 14) is.

(def fourteen (fn [] 14))
;; => #'user/fourteen
(fourteen)
;; => 14
(defn defn-fourteen [] 14)
;; => #'user/defn-fourteen
(defn-fourteen)
;; => 14
(def literal-14 #(14))
;; => #'user/literal-14
(literal-14)
;; ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn  user/literal-14 (form-init2956929406616221071.clj:1)

I don't think this is a dup of How many arguments does an anonymous function expect in clojure?, but maybe it is and I just don't possess the experience to recognize that.

How, or can, I def literal-14 to allow the (literal-14) invocation to work?

Community
  • 1
  • 1
Bob Kuhar
  • 10,838
  • 11
  • 62
  • 115

2 Answers2

11

As A. Webb pointed out, constantly is the most idiomatic way to write this:

(def fourteen (constantly 14))

The problem with the anonymous function literal is that it always expands to a function whose body is a list:

'#(stuff and things) ;=> (fn* [] (stuff and things))

So here's what's happening in your attempt:

'#(14) ;=> (fn* [] (14))

There is no way to get rid of those parentheses. You could hack your way around them using do or identity or something like that, but the bottom line is that if you need to write an anonymous function whose body isn't suited to being written as a list, you shouldn't use the literal syntax.

Community
  • 1
  • 1
Sam Estep
  • 12,974
  • 2
  • 37
  • 75
6

14 isn't a function, but do or -> will do in a pinch:

#(do 14)
#(-> 14)
ClojureMostly
  • 4,652
  • 2
  • 22
  • 24
Sean
  • 29,130
  • 4
  • 80
  • 105
  • 2
    `#(do 14)` works, `#(identity 14)` is perhaps bit more clear, and of course `(constantly 14)` is correct – A. Webb Mar 02 '16 at 02:17
  • So the first 'thing' inside a function literal has to be a function? I don't fully understand, but both the do variant and the identity variants do what I am looking for, but I am still a little fuzzy on what an anonymous function literal is. – Bob Kuhar Mar 02 '16 at 02:24
  • @BobKuhar Try `(macroexpand '#(14))`, etc. – A. Webb Mar 02 '16 at 02:27
  • @A.Webb ```(macroexpand '#(14))```, results in ```(fn* [] (14))```, which does make clear the List aspect @Elogent speaks of. But now the fn* itself is a new question. Its a different fn? What does the * do there? I can't get any doc on it. I am a rat in a maze! Thanks for your help, though. Maybe the clouds will clear. – Bob Kuhar Mar 02 '16 at 03:58
  • 1
    @BobKuhar `fn*` is the special form on top of which the `fn` macro is built. For simple cases like this one, they are equivalent. – Sam Estep Mar 02 '16 at 17:09