递归函数返回使用块不工作

时间:2012-12-17 11:45:01

标签: recursion return elisp

[解决]

我对这四个功能有类似的看法:baseinitfuncsomefunc是递归的,并自行调用:在&#34;停止案例&#34; 中,它会调用some并返回其值,然后应该< / strong>将控制权返回到&#34; init&#34;,从中调用它;后者是从base调用的。

base
  -> init
       -> func
            -> init
                 -> func
                      -> some
                    |
           _________+
          |
          v
          ; should continue from here (in `func`)

[不再]

相反,在第一次调用some后,控件直接转到base,跳过我期望的中间(init,func)对调用。

我实际上使用blockreturn和递归(例如,#34;相互尾递归factorial&#34;)尝试了几个更简单的案例,并且都运行良好。我提到func使用test catch的{​​{1}}辅助函数(但我尝试了throw的一个示例,并且没问题);只是这样,我的真实程序可能会导致问题。

这是(catch 'test (throw 'test 0)):每个elisp都以defun开头,所有函数都使用block,如下所示。

[我改用#34; return / defun&#34;到&#34; block&#34;]

defun*

(defmacro 4+ (number) "Add 4 to NUMBER, where NUMBER is a number." (list 'setq number (list '1+ (list '1+ (list '1+ (list '1+ number)))))) (defmacro 4- (number) "Subtract 4 from NUMBER, where NUMBER is a number." (list 'setq number (list '1- (list '1- (list '1- (list '1- number)))))) (defun mesg (s &optional o) "Use ATAB to tabulate message S at 4-multiple column; next/prev tab if O=1/0." (when (null o) (setq o 0)) (case o (0 (4- atab)) (1 nil)) (message (concat "%" (format "%d" (+ atab (length s))) "s") s) (case o (0 nil) (1 (4+ atab)))) (defun* base () (let (pack) (setq atab 0) (mesg "base->" 1) (setq pack (init)) (mesg "<-base"))) (defun* init () (mesg "init->" 1) (return-from init (progn (setq temp (func)) (mesg "<-init") temp))) (defun* func (&optional pack) (mesg "func->" 1) (when (not (null pack)) (return-from func (progn (mesg "<+func") pack))) (when (< 0 (mod (random) 2)); stop case (return-from func (progn (setq temp (some)) (mesg "<-func") temp))) (setq pack (init)) (case (mod (random) 2) (0 (return-from func (progn (mesg "<0func") pack))) (1 (return-from func (progn (setq temp (func pack)) (mesg "<1func") temp))) ; use tail-recursion instead of `while' (t (error "foo bar")))) (defun* some () (mesg "some->" 1) (return-from some (progn (mesg "<-some") (list 2 3 4)))) (base) 变量是我的值 - pack作为数据结构。我还使用list重复自身(在尾递归调用中)使用特殊的累积参数,这样我就可以避免&#34;命令式&#34; func。 / p>

所以不是我期望的(每个while都由>配对)

<

我的程序表现如下。

base->
    init->
        func->
            init->
                func->
                    some->
                    <-some
                <-func
            <-init
            func-> ; tail-recursion
            <+func
        <1func
    <-init
<-base

[不再]

为什么控件过早回到程序的开头,并且在第二次调用base -> init -> func -> init -> func -> some | __________________________+ | v ; control yielded here (to `base`) 之后第一次调用func时没有继续return

感谢任何帮助,

塞巴斯蒂安

2 个答案:

答案 0 :(得分:1)

查看您的代码,我不清楚func中块的范围是多少。如果块包含整个func定义,那么是,控件在返回时达到func,但是块被完全跳过,因此函数完全被跳过,并且一直向上返回它被调用的地方(最终base)。可能是这样吗?

如果是这样,你必须在块之后返回后放置你想要执行的代码。

编辑:再次查看您的代码,我认为您没有使用应该使用的return。例如在init中你有

(block nil
 ...

 (return (func ...)))

return“取消”该块,并且取消与完全没有块相同的效果,除非在“...”中调用的某个函数确实具有return 没有一个block。因此return取消func的可能返回点。

答案 1 :(得分:0)

感谢您的回答:在我的程序中插入我尝试过的消息,因为我添加的代码用于解释,显示defun*没有elisp个问题,但我在设计中误解了一些问题。