Associa più valori direttamente dall'elenco senza associare l'elenco stesso


12

È possibile assegnare più valori di ritorno direttamente alle variabili senza passare attraverso una variabile temporanea in Emacs Lisp?

Ad esempio, supponiamo che io abbia una funzione che restituisce un elenco di due elenchi:

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

Se desidero assegnare il primo valore restituito a list-ae il secondo valore restituito a list-b, posso farlo utilizzando una variabile temporanea temp, ad esempio:

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

È possibile farlo più semplicemente? (Sono abituato a Perl e Python in cui non è necessario specificare una variabile temporanea)


2
Puoi provare la cl-destructuring-bindmacro. Inoltre, hai davvero intenzione di utilizzare setqall'interno di un defun? setqcrea una variabile "speciale" (accessibile a livello globale), qualcosa che in genere si inserisce al di fuori di una funzione (perché ha poco significato nel dichiarare la stessa variabile più di una volta, mentre le funzioni devono essere eseguite più di una volta).
wvxvw,

@wvxvw Grazie! Sì, ho dimenticato di utilizzare letla funzione .. Non avevo intenzione di impostare variabili globali :)
Håkon Hægland,

Risposte:


8

Common Lisp ha una funzione speciale: più valori e la libreria di compatibilità di Emacs Lisp li emula usando gli elenchi .

Così puoi fare

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

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

(carica cl-libe usa il cl-prefisso per tutte le funzionalità CL in EL).

NB : se guardi la risposta SO collegata sopra, vedrai che emulare MV con le liste è, per usare un eufemismo, non ottimale (vedi anche il commento di @ Stefan sotto).


C'è qualche vantaggio nell'usare multiple-value-bindinvece di cl-multiple-value-bind(solo quest'ultimo sembra essere documentato nel manuale gnu.org/software/emacs/manual/html_node/cl/Multiple-Values.html )?
Håkon Hægland,

3
@ HåkonHægland Hanno la stessa funzione, ma dovresti usare quest'ultima . Il clpacchetto non è più pensato per essere utilizzato. cl-libInvece dovresti sempre usare il pacchetto, che definisce le funzioni con il cl-prefisso ..
Malabarba,

1
Lo sconsiglio di usare cl-values: è un'emulazione "del miglior sforzo" di CommonLisp valuesma non è davvero compatibile poiché tutto ciò che fa è restituire un elenco (cioè è una specie di menzogna), e nella mia esperienza le persone prima o poi finiscono manipolare quelli come liste (cioè rompere l'astrazione): usare meglio le liste in modo esplicito (e se non ti piace pcase-let, usa cl-destructuring-bindinvece che cl-multiple-value-bind).
Stefan,

4

Oltre a fare affidamento sul cl-libpacchetto di compatibilità, il modo consigliato in Elisp è quello di utilizzare 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)))

Accanto pcase-let, c'è anche pcase-dolist, pcase-lambdae pcasese stesso.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.