Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non tail-recursive anonymous functions in Clojure

Tags:

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) 
like image 446
pauldoo Avatar asked Apr 11 '11 19:04

pauldoo


People also ask

Can an anonymous function be recursive?

Anonymous recursion is primarily of use in allowing recursion for anonymous functions, particularly when they form closures or are used as callbacks, to avoid having to bind the name of the function. Anonymous recursion primarily consists of calling "the current function", which results in direct recursion.

What is non-tail recursion?

Non-Tail / Head Recursion A function is called the non-tail or head recursive if a function makes a recursive call itself, the recursive call will be the first statement in the function. It means there should be no statement or operation is called before the recursive calls.

What is difference between tailed and non-tail recursion?

In tail recursion, there is no other operation to perform after executing the recursive function itself; the function can directly return the result of the recursive call. In non-tail recursion, some operations need to be performed using the returned value of the recursive call.

Should tail recursion be avoided?

No. Go for readability. Many computations are better expressed as recursive (tail or otherwise) functions. The only other reason to avoid them would be if your compiler does not do tail call optimizations and you expect you might blow the call stack.


2 Answers

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 
like image 100
amalloy Avatar answered Oct 07 '22 18:10

amalloy


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.

like image 33
acfoltzer Avatar answered Oct 07 '22 16:10

acfoltzer