Is it possible to break out of a dolist loop? if not, are there alternatives to dolist that don't involve a while loop and indexing a list?

  • Pitingly, the while loop is excluded. IMHO it is the only pre-defined loop avoiding non-local exit when breaking out of a list iteration. It can be head or tail controlled or anything in between. – Tobias Nov 13 '19 at 7:31
  • BTW you added The catch statement evaluates to the value thrown (x in this case), or nil if no value is thrown. to lawlist's answer. How do you throw without passing a value? The VALUE arg of throw is obligatory. Maybe, you mean cl-return where it is optional. – Tobias Nov 13 '19 at 7:33
  • @Tobias it was poor wording, now corrected. – ideasman42 Nov 13 '19 at 8:28
  • I've expanded it a bit further to avoid any misunderstandings. – Tobias Nov 13 '19 at 8:54

One option is to use catch / throw:


(catch 'foo
  (dolist (x '("a" "b" "c" "d" "e" "f" "g"))
    (when (equal x "d")
      (throw 'foo x))))

The catch statement evaluates to the value thrown (x in this case), or the value of the last body form if the throw function never executes. In the case at hand the dolist form is the last entry in the body. The optional RESULT argument of (dolist (VAR LIST [RESULT]) BODY...) is not specified. Therefore, it evaluates to nil.

As pointed out by @Drew and @Tobias in comments below, the dolist function that is available without loading the cl library is defined in subr.el. Once the cl library is loaded, however, describing the function with C-h f reflects that dolist has been modified as follows: :around advice: ‘cl--wrap-in-nil-block’. The function return (which is an alias for cl-return that is defined in the cl library) can be used to break the dolist loop. To load the cl library, begin with (require 'cl):

(dolist (x '("a" "b" "c" "d" "e" "f" "g"))
  (when (equal x "d")
    (return x)))
| improve this answer | |
  • 2
    +1. Maybe make clearer that without loading library cl the version of dolist is different (not an alias for cl-dolist). You can use return (cl-return) only with the version of dolist provided by library cl (it is an alias for cl-dolist). You more or less say that, but it could be clearer - there are two different dolists, and only one lets you use return. – Drew Nov 13 '19 at 5:05
  • 1
    @Drew dolist is never an alias for cl-dolist. cl.el rather wraps dolist into a nil-block by an around advice and (cl-return val) is essentially (throw nil val). So there is not much difference between the two solutions of lawlist. The second solution is just more elegant if cl is available. – Tobias Nov 13 '19 at 5:55
  • 1
    Do not require cl. That is depreciated. Better require cl-macs or cl-lib and use cl-dolist and cl-return instead of dolist and return. Maybe, explicitly state that and give both alternative solutions. – Tobias Nov 13 '19 at 6:03
  • 1
    Citation from the cl info file: "Since the old cl.el does not use a clean namespace, Emacs has a policy that packages distributed with Emacs must not load cl at run time. (It is ok for them to load cl at compile time, with eval-when-compile, and use the macros it provides.) There is no such restriction on the use of cl-lib. New code should use cl-lib rather than cl." – Tobias Nov 13 '19 at 6:33
  • 1
    @lawlist here is the thread about cl.el = declaring obsolete: emacs.1067599.n8.nabble.com/… – Hubisan Nov 13 '19 at 9:23

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.