从 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) 只有在定义了名为 nilblock 时才会编译。某些形式隐式定义了一个名为 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" 确实如此。