「cl-flet」マクロは再帰的な関数を許可していません


7

私は廃止されたelispマクロに慣れており、fletに変更するように言われましたcl-flet。しかし、この変更を行うと、一部のelispプログラムが機能しなくなりflet、その理由は、とは異なり、cl-flet再帰的な関数が許可されていないことに気付きました。たとえば、以下の関数を定義します

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

一つは取得しないエラーを呼び出すことにより、

(show-problem-in-action 0)

出力:1

「cl-flet-defined」関数factorialは、「x = 0」の場合、それ自体を呼び出さないためです。しかしながら

(show-problem-in-action 5)

エラーを生成しますvoid-function factorial

一方、次のようなcl-flet非推奨のマクロfletで置き換える

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

再帰的な呼び出しを可能にします:

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

出力:120

cl-fletが機能しない場合、置換する代わりfletに、再帰的に関数を呼び出すことができる最善の選択肢は何ですか?


4
ところで、との決定的な違いはfletcl-flet再帰のサポートの欠如ではなく、flet動的スコープの関数定義をcl-flet提供する一方で、字句スコープの関数定義を提供するという事実です。動的スコープは、内部的に間接に依存しているため、再帰をサポートします。
Stefan

回答:


4

cl-labels代わりに使用しますcl-flet。説明はemacsマニュアルを見てください


それとも、C-h f cl-flet「そうですcl-labelsが、定義は再帰的ではありません」と言っています。
phils 2017年

答えてくれてありがとう。私が受け取った警告( 'flet'は廃止されたマクロ(24.3以降)です。'cl-flet 'または' cl-letf 'のいずれかを使用してください)も' cl-labels 'に言及されているとよいでしょうか?
2017年

私は、間に別の違いは、(苦労して)気づいたfletとはcl-labels後者の構文で定義された関数である必要があり、通常の単一引用符とは対照的に、#」引用を介して呼ぶこと。
Ruy

私の質問はこれまでに3つの賛成票を獲得cl-labelsしましたが、@ philsが指摘したように、のdoc-stringから直接回答できるため、少し恥ずかしいです。このフォーラムで不要なスペースを使い果たしていると思われる場合は、削除していただければ幸いです。
2017年

@Ruy:問題ありません。私は、この交換から何かを学びました、そして私が唯一のものであることを疑います。
ダン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.