24

How do I create a recursive anonymous function in Clojure which is not tail recursive?

The following clearly doesn't work, as recur is only for tail recursive functions. I'm also reluctant to drag in a y-combinator..

((fn [n] (if (= 1 n) 1 (* n (recur (dec n))))) 5)
1
  • "Just give it a name"? They call me Mr. Anonymous... :P~ Commented Apr 11, 2011 at 19:49

2 Answers 2

44

Functions can be given a name to refer to themselves by specifying it between fn and the arglist:

user> ((fn ! [n] (if (= 1 n) 1 (* n (! (dec n))))) 5)
120
Sign up to request clarification or add additional context in comments.

3 Comments

yay for naming anonymous functions! +1
Calling it ! seems to run counter to convention, since it's not mutating anything.
The function he's defined is the factorial function. I could have called it fact, but mathematicians call it !, and we're working in a language that allows us to call it the same. Seems silly to write something longer when everyone knows that 5! is 120.
4

Here's a way that keeps it anonymous, mostly:

(((fn [!] (fn [n] (if (= 1 n) 1 (* n ((! !) (dec n)))))) 
  (fn [!] (fn [n] (if (= 1 n) 1 (* n ((! !) (dec n))))))) 
 5)

It's not quite the Y combinator, but it does contain the same bit of self-application that allows Y to do its thing. By having a copy of the entire function in scope as ! whenever you need it, you can always make another copy.

1 Comment

You can remove some of the duplication there with this: (((fn [!] (fn [n] ((! !) n))) (fn [!] (fn [n] (if (= 1 n) 1 (* n ((! !) (dec n))))))) 5) This clearly isn't the way to do it (given that Clojure can name the fns, but I still like it. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.