从 when 语句中的函数返回
Returning from a function inside when statement
我想做的就是使用 when 语句 return 一个值 :(
我想要以下功能:
if(x)
return y
我正在尝试使用:
(when (x) y)
但是 when 语句没有以退出函数和 return y 的方式求值。它只是愉快地继续下一行。有没有一种方法可以做到这一点而不用制作一个看起来非常丑陋的 if-else 块? mzscheme/racket 不允许 1-armed ifs。
您将其标记为 Common Lisp 和 Racket,这是两种完全不同的语言。如果你正在使用 Racket 或 Scheme 并且想 return 从一个函数中提早,你可以使用一个延续来做到这一点:
(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
是唯一可移植的使用延续的方式。
上面的语句比使用 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:但是,如果您将 define/return
合并到另一个宏中,很容易不小心取消捕获 return
的定义。
然后 return
将按照您的预期行事,并且在语法上不会令人反感:
(define/return (my-function x y)
(when x (return y))
;;; more code...
)
但是,如果您使用的是 Common Lisp,情况就不同了。在 Common Lisp 中,(return y)
只有在定义了名为 nil
的 block
时才会编译。某些形式隐式定义了一个名为 nil
的块,例如 loop
宏。如果没有名为 nil
的块,您仍然可以使用命名块中的 return-from
到 return。如果您在使用 defun
定义的函数中,该函数的名称也是包装该函数的块的名称,因此这将起作用:
(defun my-function (x y)
(when x (return-from my-function y))
;;; more code
)
Racket中的一个简单方法:
(define (foo x)
(let/ec return
(when (= x 0)
(return 'zero))
'not-zero))
这里的ec代表escape continuations,比full continuations成本更低。
好吧,我会成为"that guy";有充分的理由使用 "extremely ugly" 解决方案,将函数的其余部分放在条件的 "else" 中;它使代码更易于阅读和理解。当我试图理解函数的作用时,我不想扫描所有代码寻找隐藏的 return
和奇怪的控制流。一个直截了当的'if'或'cond'就可以很清楚地说明每段代码将在什么情况下使用。
如果你认真思考为什么喜欢 "when+return" 解决方案,我怀疑在某种程度上,你想要采取这种保护措施和 "get it out of the way" 你的认知过程,让其余的功能成为焦点。这(我声称)是导致细微错误的秘诀。
搜索你的感受;你知道这是真的!
编辑:一只蚂蚁刚爬过我的笔记本电脑。这表明我说的是实话。
简单:
(and (x) y)
问题是 "when" 没有 return 值。 "and" 确实如此。
我想做的就是使用 when 语句 return 一个值 :( 我想要以下功能:
if(x)
return y
我正在尝试使用:
(when (x) y)
但是 when 语句没有以退出函数和 return y 的方式求值。它只是愉快地继续下一行。有没有一种方法可以做到这一点而不用制作一个看起来非常丑陋的 if-else 块? mzscheme/racket 不允许 1-armed ifs。
您将其标记为 Common Lisp 和 Racket,这是两种完全不同的语言。如果你正在使用 Racket 或 Scheme 并且想 return 从一个函数中提早,你可以使用一个延续来做到这一点:
(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
是唯一可移植的使用延续的方式。
上面的语句比使用 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:但是,如果您将 define/return
合并到另一个宏中,很容易不小心取消捕获 return
的定义。
然后 return
将按照您的预期行事,并且在语法上不会令人反感:
(define/return (my-function x y)
(when x (return y))
;;; more code...
)
但是,如果您使用的是 Common Lisp,情况就不同了。在 Common Lisp 中,(return y)
只有在定义了名为 nil
的 block
时才会编译。某些形式隐式定义了一个名为 nil
的块,例如 loop
宏。如果没有名为 nil
的块,您仍然可以使用命名块中的 return-from
到 return。如果您在使用 defun
定义的函数中,该函数的名称也是包装该函数的块的名称,因此这将起作用:
(defun my-function (x y)
(when x (return-from my-function y))
;;; more code
)
Racket中的一个简单方法:
(define (foo x)
(let/ec return
(when (= x 0)
(return 'zero))
'not-zero))
这里的ec代表escape continuations,比full continuations成本更低。
好吧,我会成为"that guy";有充分的理由使用 "extremely ugly" 解决方案,将函数的其余部分放在条件的 "else" 中;它使代码更易于阅读和理解。当我试图理解函数的作用时,我不想扫描所有代码寻找隐藏的 return
和奇怪的控制流。一个直截了当的'if'或'cond'就可以很清楚地说明每段代码将在什么情况下使用。
如果你认真思考为什么喜欢 "when+return" 解决方案,我怀疑在某种程度上,你想要采取这种保护措施和 "get it out of the way" 你的认知过程,让其余的功能成为焦点。这(我声称)是导致细微错误的秘诀。
搜索你的感受;你知道这是真的!
编辑:一只蚂蚁刚爬过我的笔记本电脑。这表明我说的是实话。
简单:
(and (x) y)
问题是 "when" 没有 return 值。 "and" 确实如此。