如何在任意点从函数返回?


12

您如何在函数结束前尽早返回?例如:

(defun my-func () 
 "for example."
 (unless something (return nil))
 ; continue as usual...
 (+ 42 1))

Answers:


19

我们有许多选择。

您可以catch/ throw退出功能。

例:

(defun my-func ()
  "thrown error"
  (catch 'my-catch
    (when t
      (throw 'my-catch "always going to throw"))
    (+ 42 1)))

您还可以使用blockreturn-from(尽管需要cl-macs

例:

(require 'cl-macs)

(defun my-func ()
  "block / return-from"
  (block my-func
    (when t
      (return-from my-func))
    (+ 42 1)))

cl-defun

我们也有cl-defun一个具有block与函数同名的隐式函数,因此我们可以block减少样式。

例:

(require 'cl-macs)

(cl-defun my-func ()
  "cl-defun implicit block"
  (when t
    (return-from my-func)) ; my-func is an implicit block.
  (+ 42 1)))

defun *

cl-defun也可以用作别名defun*,其定义cl.el如下:

(require 'cl)

(defun* my-func ()
  "defun* implicit block"
  (when t
    (return-from my-func)) ; my-func is an implicit block.
  (+ 42 1)))

4
请注意,如果您不喜欢CL语法,则catch/ throw会在elisp中更加惯用,因为其他方法最终都是在catch / throw方面实现的。在elisp的手册说:“大多数其他版本的Lisp语言,包括Common Lisp的,有非顺序传送控制的几种方法:returnreturn-from,和go,例如的Emacs Lisp只throw。”
phils 2015年

5

除了@EmacsFodder涵盖的内容以外,只需引发一个错误。

如果在错误处理结构(例如ignore-errors或)的范围内(动态地而非词法地)调用代码,这将无济于事condition-case,但否则,这是退出函数的一种好方法。实际上,大多数情况下都是这样做的。

(defun my-func () 
 "..."
 (unless something (error "Whoops!"))
 ; continue as usual...
 (+ 42 1))

如果您想自己处理错误,则可以将调用代码(例如,对最终调用的内容的调用my-func)放在A中condition-case。同样,这是大多数情况下执行的操作,至少与使用catch+相同throw。这完全取决于您想要的行为。


感谢Drew的回答,我同意这是一种非常普遍的方法。但是,只需使用许多其他语言尽早返回,就不会招致必须处理错误的复杂性。研究问题/答案集时。我一直在寻找“错误输出”风格的替代品,这种风格对我总是很困惑。请注意,我没有在问题文本中明确指定此内容。
ocodo 2015年

1
这完全取决于您要做什么。如果您想立即结束而不进行进一步的处理/处理,那么在Emacs中引发错误是前往非本地出口的好方法。如果你想有一个外地退出的过程中做一些事情,也就是说,处理它以某种方式,那么catchunwind-protectcondition-case等的是有用的。Elisp手册的整个章节专门介绍非本地出口。(对于IMO,其中任何一个都没有特别的困惑。)
Drew

当然,“感觉”完全是主观的。感谢您提供非本地手册参考。
ocodo 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.