我要做的就是使用when语句返回一个值:( 我想要的功能:
if(x)
return y
我正在尝试使用:
(when (x) y)
但是when语句没有以退出函数并返回y的方式进行评估。它很高兴继续下一行。有没有办法做到这一点,而不是一个非常难看的if-else块? mzscheme / racket不允许单臂ifs。
答案 0 :(得分:7)
好的,我将成为"那个家伙&#34 ;;使用"极其丑陋的"把剩下的功能放在" else"有条件的;它使代码更易于阅读和理解。当我试图理解函数的作用时,我不想扫描所有代码搜索隐藏的return
和奇怪的控制流。一个直截了当的“如果'或者' cond'非常清楚在什么情况下将使用每一段代码。
如果你认真思考为什么你喜欢"当+返回"解决方案,我怀疑在某种程度上,你想要抓住那个后卫并且#34;让它脱离困境"你的认知过程,让其余的功能成为焦点。这(我声称)是一个微妙的错误的配方。
搜索你的感受;你知道这是真的!
编辑:一只蚂蚁爬过我的笔记本电脑。这是我说出真相的标志。答案 1 :(得分:5)
Racket中的一个简单方法:
(define (foo x)
(let/ec return
(when (= x 0)
(return 'zero))
'not-zero))
这里ec代表逃避延续,它比完全延续便宜。
答案 2 :(得分:2)
您将此标记为Common Lisp和Racket,它们是两种完全不同的语言。如果您正在使用Racket或Scheme并希望尽早从函数返回,则可以使用延续来执行此操作:
(define (my-function x y)
(call-with-current-continuation
(lambda (return)
(when x (return y))
;; Rest of code not evaluated if X is true
)))
在包括Racket在内的一些Scheme实现中,call-with-current-continuation
也绑定到call/cc
,但call-with-current-continuation
是唯一可以使用continuation的可移植方式。
上述内容甚至比使用cond
语句更加丑陋。如果你想摆脱所有额外的废话,你可以定义一个宏来创建define
的替代版本,自动创建延续并将其绑定到return
:
(define-syntax define/return
(syntax-rules ()
((_ (name . args) . body)
(define (name . args)
(capture-vars (return)
(call/cc (lambda (return) . body)))))))
这需要您拥有我的capture-vars
宏,您可以在this answer找到它。
编辑:Leppie提供了define/return
的以下实施,这更简单,因为它不需要我的capture-vars
宏:
(define-syntax define/return
(lambda (x)
(syntax-case x ()
[(_ (name . args) . body)
(with-syntax
([return (datum->syntax #'name 'return)])
#'(define (name . args)
(call/cc (lambda (return) . body))))])))
编辑2:但是,如果您将return
合并到另一个宏中,则很容易意外地取消define/return
这样做的定义。
然后return
会按照您的预期行事,而不会在语法上令人反感:
(define/return (my-function x y)
(when x (return y))
;;; more code...
)
但是,如果您使用Common Lisp,情况会有所不同。在Common Lisp中,(return y)
只会在定义名为block
的{{1}}时进行编译。某些表单隐式定义名为nil
的块,例如nil
宏。如果没有名为loop
的块,您仍然可以使用nil
从命名块返回。如果您在使用return-from
定义的函数中,该函数的名称也是包装该函数的块的名称,因此这将起作用:
defun
答案 3 :(得分:0)
简单:
(and (x) y)
问题是“何时”不返回值。 “和”可以。