12

Is it possible to assign multiple return values directly to variables without going through a temporary variable in Emacs Lisp?

For example, let's say I have a function that returns a list of two lists:

(defun test-func ()
  (setq a '(a b))
  (setq b '(c d))
  `(,a ,b))

If I want to assign the first return value to list-a and the second return value to list-b, I can do this by using a temporary variable temp, for example:

(let* ((temp (test-func)) (list-a (car temp)) (list-b (cadr temp)))
  (message-box (prin1-to-string list-a))
  (message-box (prin1-to-string list-b)))

Is it possible to do this more simply? (I am used to Perl and Python where you do not have to specify a temporary variable)

  • 2
    You may try cl-destructuring-bind macro. Also, did you really intend to use setq inside a defun? setq creates a "special" (globally accessible) variable, something you'd typically put outside a function (because there's little meaning in declaring the same variable more than once, while functions are intended to be run more than once). – wvxvw Jan 26 '15 at 10:54
  • @wvxvw Thanks! Yes I forgot to use let inside the function.. I did not plan to set any global variables :) – Håkon Hægland Jan 26 '15 at 11:23
8

Common Lisp has a special facility - multiple values, and Emacs Lisp compatibility library emulates them using lists.

Thus you can do

(defun test-fun ()
  (let ((a 1) (b 2))
    (cl-values a b)))

(cl-multiple-value-bind (a b) (test-fun)
  ...)

(load cl-lib and use the cl- prefix for all CL functionality in EL).

NB: if you look at the SO answer linked above, you will see that emulating MV with lists is, to put it mildly, suboptimal (see also @Stefan's comment below).

| improve this answer | |
  • Is there any advantage of using multiple-value-bind instead of cl-multiple-value-bind (only the latter seems to be documented in the manual gnu.org/software/emacs/manual/html_node/cl/Multiple-Values.html ) ? – Håkon Hægland Jan 26 '15 at 11:50
  • 3
    @HåkonHægland They are the same function, but you should use the latter. The cl package is not meant to be used anymore. You should always use the cl-lib package instead, which defines functions with the cl- prefix.. – Malabarba Jan 26 '15 at 11:54
  • 1
    I'd recommend against the use of cl-values: it's a "best effort" emulation of CommonLisp's values but it's not really compatible since all it does is return a list (i.e. it's kind of a lie), and in my experience people sooner or later end up manipulating those as lists (i.e. breaking the abstraction): better use lists explicitly (and if you don't like pcase-let, then use cl-destructuring-bind rather than cl-multiple-value-bind). – Stefan Jul 9 '18 at 15:59
4

Beside relying on the cl-lib compatibility package, the recommended way in Elisp for that is to use pcase:

(defun test-fun
  (let ((a '(a b))
        (b '(c d)))
    `(,a ,b)))

(defun other-test-fun ()
  (pcase-let ((`(,a ,b) (test-fun)))
    (message "a = %s; b = %s" a b)))

Beside pcase-let, there's also pcase-dolist, pcase-lambda, and pcase itself.

| improve this answer | |

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.