Automatic TCO in Clojure

Is there a way to define a function in Clojure that is automatically tail-optimized?

eg.

(defrecur fact [x] (if (= x 1) 1 (* x (fact (dec x))))) 

will be internally translated to something like:

 (defn fact [x] (loop [nxf 1] (if (= n 1) f (recur (dec n) (* fn))))) 

Can you tell me if something like this already exists?

+1
source share
3 answers

The short answer is "no."

A slightly longer answer is that Clojure is intentionally designed to require a clear indication of where Tail Call optimization is required because the JVM does not support it natively.

By the way, you can use recur without loop , so you no longer need to enter text, for example:

 (defn func [x] (if (= x 1000000) x (recur (inc x)))) 

Update , April 29th:

Chris Frieze is working on a Clojure TCO project with Dan Friedman, and while no one claims to be the β€œanswer” at this time, the project is interesting and promising. Chris recently gave an unofficial report on this project, and published it on his blog .

+2
source

As far as I know, there is no automatic way to generate tail recursion in Clojure.

There are examples of functions that use recursion without using a loop. recur that work without. This is because these functions have been carefully written to use lazy sequences.

Here is an example of replacing anti-aliasing with a handwritten function. This example came from http://yyhh.org/blog/2011/05/my-solutions-first-50-problems-4clojure-com

 (fn flt [coll] (let [l (first coll) r (next coll)] (concat (if (sequential? l) (flt l) [l]) (when (sequential? r) (flt r))))) 
+1
source

One of the guiding principles behind this decision was for the special part to look special . thus, it is obvious that tail calls are used, and where not. It was a deliberate design decision on which some people have strong opinions, although in practice I rarely see the recur used in idomatic Clojure anyway , so in practice this is not a common problem.

+1
source

Source: https://habr.com/ru/post/1237422/


All Articles