我有一个递归函数,需要递归,直到找到一定的结果.然而,在我的第一次递归调用后,我的函数体中可能会做一些其他的计算或者可能再次递归.但是,如果我递归并找到我正在寻找的结果,那么我想停止我正在做的任何递归并返回该结果以避免进行不必要的计算.
在正常的递归调用中,一旦你到达被调用的函数返回的"基本情况",那么它将返回到调用它的那个,依此类推.我想知道如何在第一次调用函数时返回,而不必为所有这些中间步骤返回一些东西.
对于我的基本递归,我可以写一个这样的函数:
(defun recurse (x)
(if (= x 10)
(return-from recurse x)
(progn (recurse (+ x 1)) (print "Recursed!")))))
(recurse 1)
Run Code Online (Sandbox Code Playgroud)
编写它是为了说明我在递归调用后运行更多计算的函数的含义.并且,正如所写,这甚至没有返回我感兴趣的值,因为我在返回我关心的值之后进行了一些打印.(注意:return-from命令在这里是无关紧要的,因为我可以在它的位置写"x".当我尝试在下面的第二个例子中返回顶级递归时,它就是在那里画出相似之处.)
现在,如果我想抛弃所有额外的"递归!" 打印我可以将所有内容包含在一个块中,然后返回到该块:
编辑:这是我原始示例的函数包装器.这个例子现在应该更清楚了.
(defun recurse-to-top (start)
(block top-level
(labels ((recurse (x)
(if (= x 10)
(return-from top-level x)
(progn (recurse (+ x 1)) (print "Recursed!")))))
(recurse start))))
Run Code Online (Sandbox Code Playgroud)
并且运行此块一直持续到"找到10",然后从顶层块返回,没有任何无关的打印,就像我想要的那样.但是,这似乎是获得此功能的一种非常笨重的方式.我想知道是否有一种标准或"最佳"的方式来获得这种行为.
我是Lisp的新手,我遇到了打印问题.我有一个函数可以打印到标准输出(除其他外).我想通过另一个函数运行此函数,它仍然运行相同但没有任何东西被打印到标准输出.
这是我的意思的一个简单例子.我有以下两个功能描述:
(defun does-printing()
(print "This goes to standard output."))
(defun run-other-function (function)
(funcall function)
(values))
Run Code Online (Sandbox Code Playgroud)
这是我运行时发生的运球,
;; Dribble of #<IO TERMINAL-STREAM> started on 2014-10-05 21:49:49.
#<OUTPUT BUFFERED FILE-STREAM CHARACTER #P"example.out">
[7]> (run-other-function #'does-printing)
"This goes to standard output."
[8]> (dribble)
;; Dribble of #<IO TERMINAL-STREAM> finished on 2014-10-05 21:50:09.
Run Code Online (Sandbox Code Playgroud)
请注意,打印功能仍然打印到标准输出.它希望能够通过run-other-function运行打印时以某种方式抑制此打印.在搜索解决方案时,我已经尝试了许多不同的措辞,但我没有想到要做什么.
在函数调用中定义时,我在理解变量和函数的范围时遇到了一些麻烦.我试着搜索这个范围,但找不到合适的答案(或者可能是在寻找错误的东西),所以我决定写一些函数来自己测试一下:
(defun test-scope1 ()
(setf myvar 1)
(defun set-var1 ()
(setf myvar 2))
(set-var1))
Run Code Online (Sandbox Code Playgroud)
有了这个功能,我只想看看是否有任何东西设置为全局.我希望myvar和set-var能够全局定义,因为我这里没有范围.正如预期的那样,在调用(test-scope1)
命令myvar
并(set-var)
给我错误之前.在打电话之后(test-scope1)
,我可以在翻译中运行myvar
并(set-var)
获得2.
想一想我自己封装变量会很好,我决定在我的函数中添加一个let,因此得到我的下一个测试:
(defun test-scope2 ()
(let ((myvar 10))
(defun set-var2 ()
(setf myvar 20))
(set-var2)))
Run Code Online (Sandbox Code Playgroud)
我希望myvar
被困在let块的范围内,但无法猜测set-var2
.它可以卡在let块中,也可以全局定义.运行后(test-scope2)
我尝试访问myvar
并获得2.这意味着这个新函数有自己的myvar,因为它仍然是前一个函数的2.我试着跑步(set-var2)
,得到20分.
在let块中运行后,函数是全局定义的,我并不感到惊讶,但现在我很困惑myvar变量的访问权限.因为它没有改变myvar的全局副本,所以看起来它周围有一些浮动的变量仍然是指.
现在我想看看我是否可以操作那个浮动变量,所以我创建了第三个函数.
(defun test-scope3 ()
(let ((myvar (if (ignore-errors myvar)
myvar
100)))
(defun set-var3 ()
(setf myvar (+ myvar 100)))
(set-var3)))
Run Code Online (Sandbox Code Playgroud)
我不想仅仅将变量设置为固定值,而是根据之前的值增加它.我在这里检查两件事.第一个是调用test-scope3的时候.我想知道我是否可以提取myvar的"之前的值",因为如果它漂浮在某个地方,我可以再次访问它.这可能不是一个好习惯,但这不是重点.如果没有真正的先前值浮动,则忽略错误,在这种情况下,我选择默认值100.
我测试的第二件事是让set-var3将前一个myvar的值加100.我想看看这是否会调整浮动变量,或者某种方式是静态的.我不知道我的功能"应该"返回什么.
运行后(test-scope3)
我完全惊讶地看到102.显然我的test-scope3在运行test-scope1时找到了myvar的值.但是,在检查解释器中myvar的值之后,它仍然是2.接下来我运行(set-var3)
并获得202的返回值.好的,所以它再次添加100到我之前的值.再次调用它会返回302,依此类推.但是, …