Common Lisp Contro Contro crea un elenco da due simboli, Clojure Contro richiede un Seq a contro?
-
13-09-2020 - |
Domanda
(Disclaimer - Sono consapevole del significato di SEQ in Clojure)
In comune Lisp La funzione Contro può essere utilizzata per combinare due simboli in un elenco:
(def s 'x)
(def l 'y)
(cons s l)
.
In Clojure - puoi solo contro una sequenza - i contro non sono stati estesi per funzionare con due simboli.Quindi devi scrivere:
(def s 'x)
(def l 'y)
(cons s '(l))
.
C'è un modello di livello superiore in clojure che spiega questa differenza tra lisp e clojure comune?
Soluzione
In Clojure, a differenza dei lisp tradizionali, gli elenchi non sono le strutture dei dati primari. Le strutture di dati possono implementare il ISEQ Interfaccia - Qual è un'altra vista della struttura dei dati che è data, consentendo alle stesse funzioni di accedere agli elementi in ciascuna. (Elenchi già implementarlo. seq?
controlla se qualcosa implementa ISEQ . (seq? '(1 2)), (seq? [1 2]))
Clojure Agisce semplicemente (con buona ragione), in quanto quando viene utilizzato cons
, una sequenza (è in realtà di tipo clojure.lang.Cons
) costruito in generazione a
e (seq b)
viene restituito. (a
Arg 1 e b
Arg 2) Ovviamente, i simboli non possono implementare ISEQ .
Sequenze Screencast / Talk per ricco hickey Tuttavia, nota che rest
è cambiato e Il comportamento precedente è ora in next
, e che lazy-cons
è stato sostituito da lazy-seq
e cons
.
Altri suggerimenti
In Common Lisp Contro Contro crea una cosiddetta cella Contro, che è simile a un record con due slot: la 'auto' e 'cdr'.
Puoi mettere qualsiasi cosa in quei due slot di una cella contro.
contro le celle sono utilizzate per creare liste.Ma si può creare tutti i tipi di strutture di dati con le celle dei contro: alberi, grafici, vari tipi di liste specializzate, ...
Le implementazioni di LISP sono altamente ottimizzate per fornire celle contro molto efficienti.
Un elenco di Lisp è solo un modo comune di utilizzare le celle dei contro (vedere Descrizione di Rainer ).Clojure è meglio visto come non avere celle contro (anche se qualcosa di simile potrebbe nascondersi sotto il cappuccio).Il cons
di Clojure è un termine sbagliato, dovrebbe effettivamente essere denominato prepend
.
In Clojure L'uso di un vettore a due elementi è preferito: [:a :b]
.Sotto il cofano tali piccoli vettori sono implementati come array Java e sono estremamente semplici e veloci.
Una mano corta per (cons :a '(:b))
(o (cons :a (cons :b nil))
) è list
: (list :a :b)
.
Quando dici
> (cons 'a 'b)
.
In comune Lisp non hai ricevuto una lista ma una coppia tratteggiata: (a . b)
, mentre il risultato di
> (cons 'a (cons 'b nil))
.
è la coppia punteggiata (a . ( b . nil))
.
Nel primo elenco il cdr()
di ciò non è un elenco, poiché è qui b
e non nil
, rendendolo un elenco improprio.Gli elenchi appropriati devono essere terminati da nil
.Pertanto funzioni di ordine superiore come mapcar()
e gli amici non funzioneranno, ma salviamo un contenitore.Immagino che i progettisti di Clojure rimossi questa funzione a causa della confusione che potrebbe causare.