12

How do you return early from a function before it's ended? For example:

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

We have a number of options available.

Throw

You can catch / throw to exit the function.

example:

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

Block

You can also use block and return-from (although you will need to require cl-macs)

example:

(require 'cl-macs)

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

cl-defun

We also have cl-defun which has an implicit block with the same name as the function, so we can do the block style with less.

example:

(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 is also available as an alias defun* which is defined in cl.el so:

(require 'cl)

(defun* my-func ()
  "defun* implicit block"
  (when t
    (return-from my-func)) ; my-func is an implicit block.
  (+ 42 1)))
  • 4
    Note that if you don't have a preference for the CL syntax, catch/throw is more idiomatic in elisp, as other approaches are ultimately implemented in terms of catch/throw. The elisp manual says: "Most other versions of Lisp, including Common Lisp, have several ways of transferring control nonsequentially: return, return-from, and go, for example. Emacs Lisp has only throw." – phils Jan 31 '15 at 5:28
4

In addition to what @EmacsFodder covered, just raise an error.

This will not help if the code is called within (dynamically, not lexically) the extent of error-handling constructs such as ignore-errors or condition-case, but otherwise it is a fine way to exit a function. It is in fact what is done most of the time.

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

If you want to handle the error yourself then you can put the calling code (e.g. the call to something that ulimately calls my-func) inside a condition-case. Again, this is what is done most of the time, at least as often as using catch + throw. It all depends on what behavior you want.

  • Thanks for the answer Drew, I agree this is quite a common method. However, just doing an early return in a lot of other languages, doesn't incur the complexity of having to then deal with an error. When researching the question/answer set. I was specifically looking for alternatives to the "erroring out" style which always feels kludgy to me. I didn't specify this explicitly in the question text mind you. – ocodo Feb 1 '15 at 1:00
  • 1
    It all depends on what you want to do. If you want to end immediately, with no further processing/handling, then raising an error is a good way to go for a nonlocal exit, in Emacs. If you want to do something during a nonlocal exit, i.e., handle it in some way, then catch, unwind-protect, condition-case and the like are useful. There is a whole section of the Elisp manual devoted to nonlocal exits. (And there is nothing particularly kludgy about any of them, IMO.) – Drew Feb 1 '15 at 2:54
  • "Feels" is entirely subjective of course. Thanks for the nonlocal manual ref. – ocodo Feb 1 '15 at 2:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.