[解决]
我对这四个功能有类似的看法:base
,init
,func
和some
。 func
是递归的,并自行调用:在"停止案例" 中,它会调用some
并返回其值,然后应该< / strong>将控制权返回到&#34; init
&#34;,从中调用它;后者是从base
调用的。
base
-> init
-> func
-> init
-> func
-> some
|
_________+
|
v
; should continue from here (in `func`)
[不再]
相反,在第一次调用some
后,控件直接转到base
,跳过我期望的中间(init,func)
对调用。
我实际上使用block
,return
和递归(例如,#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
?
感谢任何帮助,
塞巴斯蒂安
答案 0 :(得分:1)
查看您的代码,我不清楚func
中块的范围是多少。如果块包含整个func
定义,那么是,控件在返回时达到func
,但是块被完全跳过,因此函数完全被跳过,并且一直向上返回它被调用的地方(最终base
)。可能是这样吗?
如果是这样,你必须在块之后返回后放置你想要执行的代码。
编辑:再次查看您的代码,我认为您没有使用应该使用的return
。例如在init
中你有
(block nil
...
(return (func ...)))
此return
“取消”该块,并且取消与完全没有块相同的效果,除非在“...
”中调用的某个函数确实具有return
没有一个block
。因此return
取消func
的可能返回点。
答案 1 :(得分:0)
感谢您的回答:在我的程序中插入我尝试过的消息,因为我添加的代码用于解释,显示defun*
没有elisp
个问题,但我在设计中误解了一些问题。