【问题标题】:recursive function return using block not working使用块的递归函数返回不起作用
【发布时间】:2012-12-04 12:18:38
【问题描述】:

[已解决]

这四个函数我有类似的东西:baseinitfuncsomefunc 是递归的并调用自身:在 "stop case" 中,它将调用 some 并返回其值,然后它应该将控制权返回给 "@ 987654327@",从中调用它;后者曾被base 调用。

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

[不再]

相反,在第一次调用some 之后,控制权直接交给base,跳过了我期望的中间(init,func) 对调用。

我实际上使用blockreturn 和递归(例如,“相互尾递归factorial”)尝试了几个更简单的情况,并且都运行良好。我提到func 使用test 辅助函数catchthrow(但我什至尝试了(catch 'test (throw 'test 0)) 的示例,没关系);就是这样,我的真实程序可能会导致问题。

这是elisp:每个defun都以block开头,所有函数都使用return,如下所示。

[我从使用“defun/block”切换到“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 作为数据结构。我还使用func 用一个特殊的累积参数重申自己(在尾递归调用中),这样我就可以避免 "imperative" while

所以不是我所期望的(每个&gt; 都由&lt; 配对)

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,在第二次通过init 调用return 之后继续?

感谢任何帮助,

塞巴斯蒂安

【问题讨论】:

  • 对不起,我现在输入some
  • @Stefan:换句话说,是否有一些以前遇到过的函数/部分/问题已知的[e]lisp可能最少 i> 与block/return 技术交互? (即函数string-match ...?)。我在公共存储库中有代码,但最终我只有 20%,它与解析 LaTeX 代码行有关。

标签: recursion return elisp


【解决方案1】:

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

如果是这样,您必须将要在 return 之后执行的代码放在块之后。

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

(block nil
 ...

 (return (func ...)))

这个return“取消”了这个块,和根本没有这个块的效果一样,除非在“...”中调用的某些函数确实有一个return没有block。所以这里的return取消了func可能的返回点。

【讨论】:

  • 我的意思是 block 包装了所有其他代码,包括任何 [无条件] return 和条件 return “点”,因此取消了其余的,但不是 block 代表defun 返回的值,是当前值,不是幻像。
  • 你到底是什么意思?来自同一defun/block 内部的所有return 点以什么方式相互排斥?
  • 我重读了您的回答。你是对的,但情况是block extent 包装了所有函数体,也就是说,就 elisp 解释器而言,它是“唯一的函数”。
【解决方案2】:

感谢您的回答:将我尝试使用的那些消息插入到我的程序中,就像我为解释添加的代码一样,elisp 没有 defun* 问题,但我在设计中犯了一些错误。

【讨论】:

    猜你喜欢
    • 2014-05-20
    • 1970-01-01
    • 2019-03-04
    • 2018-07-14
    • 2018-04-02
    • 2014-04-03
    • 2017-01-12
    • 2015-10-22
    相关资源
    最近更新 更多