Macro "cl-flet" que não permite funções recursivas

7

Estou acostumado com a macro elisp obsoleta flete me disseram para mudar para cl-flet. No entanto, ao fazer essa alteração, alguns dos meus programas elisp pararam de funcionar e percebi que o motivo é que, diferentemente flet, cl-fletnão permite funções recursivas. Por exemplo, definindo a função abaixo

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

ninguém recebe erro chamando

(show-problem-in-action 0)

Saída: 1

porque a função "cl-flet-defined" factorialnão se chama quando "x = 0". Contudo

(show-problem-in-action 5)

produz o erro void-function factorial.

Por outro lado, substituindo cl-fletpor sua macro obsoleta flet, como abaixo

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

permite invocação recursiva:

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

Saída: 120

Se cl-fletnão estiver funcionando, qual seria minha melhor alternativa para substituir flet, ainda sendo capaz de chamar funções recursivamente?

Ruy
fonte
4
BTW, a diferença crucial entre flete cl-fletnão é a falta de suporte à recursão, mas o fato de fletfornecer definições de função com escopo dinâmico, enquanto cl-fletfornece definições de função com escopo lexicamente. O escopo dinâmico fornece suporte para recursão em virtude de depender internamente de um indireto.
Stefan

Respostas:

4

Use em cl-labelsvez de cl-flet. Para obter uma explicação, consulte o manual do emacs

siehe-falz
fonte
Ou, de fato, C-h f cl-fletque diz "Gostar, cl-labelsmas as definições não são recursivas".
phils
Obrigado pela resposta. Não seria bom se o aviso que recebi ('flet' é uma macro obsoleta (a partir de 24.3); use 'cl-flet' ou 'cl-letf') também mencionasse 'cl-labels'?
Ruy
Notei (da maneira mais difícil) que outra diferença entre flete cl-labelsé que as funções definidas com a última sintaxe devem ser mencionadas através da citação # ', em oposição à aspas simples usuais.
Ruy
Apesar de minha pergunta ter recebido três votos positivos até agora, estou um pouco envergonhada porque ela pode ser respondida diretamente da sequência de documentos de cl-labels, como apontado por @phils. Ficarei feliz em excluí-lo, se alguém achar que está usando espaço desnecessário neste fórum.
Ruy
@ Ruy: não há problema algum. Eu aprendi algo com essa troca e duvido que seja o único.
Dan