How do I make a literal function that takes no args and return a constant value?
Asked Answered
G

2

5

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?

Gorse answered 2/3, 2016 at 2:5 Comment(1)
(fn [& args] x)Abuzz
P
7

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

#(do 14)
#(-> 14)
Passerby answered 2/3, 2016 at 2:14 Comment(5)
#(do 14) works, #(identity 14) is perhaps bit more clear, and of course (constantly 14) is correctTwowheeler
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.Gorse
@BobKuhar Try (macroexpand '#(14)), etc.Twowheeler
@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.Gorse
@BobKuhar fn* is the special form on top of which the fn macro is built. For simple cases like this one, they are equivalent.Letaletch
L
12

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.

Letaletch answered 2/3, 2016 at 3:16 Comment(0)
P
7

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

#(do 14)
#(-> 14)
Passerby answered 2/3, 2016 at 2:14 Comment(5)
#(do 14) works, #(identity 14) is perhaps bit more clear, and of course (constantly 14) is correctTwowheeler
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.Gorse
@BobKuhar Try (macroexpand '#(14)), etc.Twowheeler
@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.Gorse
@BobKuhar fn* is the special form on top of which the fn macro is built. For simple cases like this one, they are equivalent.Letaletch

© 2022 - 2024 — McMap. All rights reserved.