Binden Sie mehrere Werte direkt aus der Liste, ohne die Liste selbst zu binden


12

Ist es möglich, Variablen mehrere Rückgabewerte direkt zuzuweisen, ohne eine temporäre Variable in Emacs Lisp zu durchlaufen?

Angenommen, ich habe eine Funktion, die eine Liste mit zwei Listen zurückgibt:

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

Wenn ich den ersten Rückgabewert list-aund den zweiten Rückgabewert zuweisen möchte list-b, kann ich dazu eine temporäre Variable verwenden temp, zum Beispiel:

(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)))

Kann man das einfacher machen? (Ich bin Perl und Python gewohnt, bei denen Sie keine temporäre Variable angeben müssen.)


2
Sie können cl-destructuring-bindMakro versuchen . Wollten Sie auch wirklich setqin einem verwenden defun? setqerstellt eine "spezielle" (global zugreifbare) Variable, die Sie normalerweise außerhalb einer Funktion platzieren würden (da es wenig Sinn macht, dieselbe Variable mehr als einmal zu deklarieren, während Funktionen mehr als einmal ausgeführt werden sollen).
wvxvw

@wvxvw Danke! Ja, ich habe vergessen, letinnerhalb der Funktion zu verwenden .. Ich hatte nicht vor, globale Variablen zu setzen :)
Håkon Hægland

Antworten:


8

Common Lisp hat eine spezielle Funktion - mehrere Werte , und die Emacs Lisp-Kompatibilitätsbibliothek emuliert sie mithilfe von Listen .

So können Sie tun

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

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

(Laden cl-libund verwenden Sie das cl-Präfix für alle CL-Funktionen in EL).

NB : Wenn Sie sich die oben verlinkte SO-Antwort ansehen, werden Sie sehen, dass das Emulieren von MV mit Listen, gelinde gesagt, suboptimal ist (siehe auch @ Stefans Kommentar unten).


Gibt es einen Vorteil der Verwendung multiple-value-bindanstelle von cl-multiple-value-bind(nur letzteres scheint im Handbuch gnu.org/software/emacs/manual/html_node/cl/Multiple-Values.html dokumentiert zu sein )?
Håkon Hægland

3
@ HåkonHægland Sie haben die gleiche Funktion, aber Sie sollten die letztere verwenden . Die clPackung ist nicht mehr zum Gebrauch bestimmt. Sie sollten cl-libstattdessen immer das Paket verwenden, das Funktionen mit dem cl-Präfix definiert.
Malabarba

1
Ich würde gegen die Verwendung von empfehlen cl-values: Es ist eine "Best Effort" -Emulation von CommonLisp, valuesaber nicht wirklich kompatibel, da es nur eine Liste zurückgibt (dh es ist eine Art Lüge), und meiner Erfahrung nach landen die Leute früher oder später Manipulieren dieser als Listen (dh Brechen der Abstraktion): Verwenden Sie Listen besser explizit (und wenn Sie nicht mögen pcase-let, verwenden Sie cl-destructuring-bindlieber als cl-multiple-value-bind).
Stefan

4

cl-libAbgesehen davon, dass Sie sich auf das Kompatibilitätspaket verlassen, ist die in Elisp empfohlene Methode, Folgendes zu verwenden 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)))

Neben pcase-letgibt es auch pcase-dolist, pcase-lambdaund pcaseselbst.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.