8

I am used to the deprecated elisp macro flet and I was told to change to cl-flet. However upon making this change some of my elisp programs stopped working and I realized the reason is that, unlike flet, cl-flet does not allow for recursive functions. For example, defining the function below

(defun show-problem-in-action (x)
  (cl-flet (
    (factorial (n)
      (if (= n 0)
        1
        (* n (factorial (- n 1))) )))
  (factorial x) ))

one gets no error by calling

(show-problem-in-action 0)

Output: 1

because the "cl-flet-defined" function factorial does not call itself when "x=0". However

(show-problem-in-action 5)

produces the error void-function factorial.

On the other hand, replacing cl-flet by its deprecated macro flet, such as below

(defun no-problem-with-deprecated-macro (x)
  (flet (
    (factorial (n)
      (if (= n 0)
        1
        (* n (factorial (- n 1))) )))
  (factorial x) ))

allows for recursive invocation:

(no-problem-with-deprecated-macro 5)

Output: 120

If cl-flet is not working, what would be my best alternative to replace flet with, still being able to call functions recursively?

Drew
  • 75,699
  • 9
  • 109
  • 225
Ruy
  • 787
  • 4
  • 11
  • 4
    BTW, the crucial difference between `flet` and `cl-flet` is not the lack of support for recursion but the fact that `flet` provides dynamically-scoped function definitions, whereas `cl-flet`provides lexically-scoped function definitions. Dynamic scoping happens to provide support for recursion by virtue of relying internally on an indirection. – Stefan Oct 30 '17 at 13:09

1 Answers1

5

Use cl-labels instead of cl-flet. For explanation look at the emacs manual

Stefan
  • 26,154
  • 3
  • 46
  • 84
siehe-falz
  • 201
  • 1
  • 1
  • Or indeed `C-h f cl-flet` which says "Like `cl-labels` but the definitions are not recursive." – phils Oct 30 '17 at 12:32
  • Thanks for the answer. Wouldn't it be nice if the warning I got ('flet' is an obsolete macro (as of 24.3); use either 'cl-flet' or 'cl-letf') also mentioned 'cl-labels'? – Ruy Oct 30 '17 at 13:22
  • 1
    I noticed (the hard way) that another difference between `flet` and `cl-labels` is that functions defined with the latter syntax **must** be referred to via the #' quotation, as opposed to the usual single-quote. – Ruy Oct 30 '17 at 18:26
  • Despite the fact that my question got three up-votes so far, I am a bit embarrassed because it can be answered straight from the doc-string of `cl-labels`, as pointed out by @phils. I'll be glad to delete it should anybody think it is using up unnecessary space in this forum. – Ruy Oct 31 '17 at 12:06
  • 1
    @Ruy : no problem at all. I, for one, learned something from this exchange, and I doubt I’ll be the only one. – Dan Nov 01 '17 at 00:37
  • @Ruy please leave it up, this is the first Google result for "cl recursive flet" :) and your comment about `#'` is poignant. – hraban Jul 07 '22 at 03:02