2009-07-23 14 views
7

Sto imparando il concetto di sequence e nil in Clojure. Questo è stato il risultato di una piccola sperimentazione.In Clojure è una lista vuota una sequenza di null infiniti?

1:6 user=> (first '()) 
nil 
1:7 user=> (rest '()) 
() 
1:8 user=> (first (rest '())) 
nil 

Ciò significa che '() è in realtà una sequenza di nils?

risposta

9

Se si desidera verificare se il "resto" di una raccolta è vuoto, utilizzare next.

user> (next '(foo bar)) 
(bar) 
user> (next '()) 
nil 
user> (doc next) 
------------------------- 
clojure.core/next 
([coll]) 
    Returns a seq of the items after the first. Calls seq on its 
    argument. If there are no more items, returns nil. 

"zero-giochi di parole" (il trattamento di un vuoto di raccolta/ss e nil come la stessa cosa) è stato rimosso lo scorso anno a favore di sequenze completamente pigri. Vedere here per una discussione che porta a questa modifica.

+0

Quando scrivo le frasi cond per ricorrere in sequenza, il mio primo controllo è di solito (vuoto? Obj). È il modo corretto di recidivare in Clojure? – unj2

+3

Penso che di solito le persone testano (seq obj) piuttosto che '(empty? Obj)'. –

+0

@BrianCarper Perché? C'è una differenza significativa tra le due espressioni? – wrongusername

1

Apprendimento anche Clojure.

Per vuoto sequences, rest restituisce una sequenza per cui seq restituisce nil.

Ecco perché ottieni questo comportamento.

assumo questo è semplificare recursing sulle sequenze fino a quando sono vuote, e probabilmente altre ragioni Smartypants ...

4

first e rest sono funzioni che si applicano ad una struttura logica (un seq) e non sul collegato struttura dei contro di una lista (come in altre lisps).

Clojure definisce molti algoritmi in termini di sequenze (seq). Un seq è un elenco logico e, a differenza della maggior parte dei Lisps in cui l'elenco è rappresentato da una struttura concreta a 2 slot, Clojure utilizza l'interfaccia ISeq per consentire a molte strutture di dati di fornire l'accesso ai propri elementi come sequenze.

http://clojure.org/sequences

Il comportamento è il risultato della definizione della funzione e non determinato dalla struttura primitiva dei dati.

0

Tecnicamente sebbene non in un modo utile.

"La sequenza che viene creata chiamando (seq '()) ha un numero infinito di null?"
la risposta è sì becase il (resto) di una sequenza vuota è davanzale una sequenza vuota che è di per sé può avere un (riposo)

Questa uscita è fuorviante proposito:

 
1:7 user=> (rest '()) 
() 

il primo '() in questo è l'elenco vuoto .
il secong() in questo è la sequenza vuota . Le sequenze
vengono stampate come le liste nel repl, anche se non sono uguali.

2

No - un elenco vuoto, non è la stessa di una sequenza infinita di Nils

Questo è relativamente facile da mostrare. Supponiamo di avere:

(def infinite-nils (repeat nil)) ; an infinite lazy sequence of nils 
(def empty-list '())   ; an empty list 

Hanno un diverso numero di elementi:

(count infinite-nils) => doesn't terminate 
(count empty-list) => 0 

Prendendo da loro:

(take 10 infinite-nils) => (nil nil nil nil nil nil nil nil nil nil) 
(take 10 empty-list)  =>() 

Se si chiama ss su di loro si ottiene

(seq inifinite-nils) => sequence of infinite nils 
(seq empty-list)  => nil 

La confusione nell'originale può essere più ampia y essere risolto attraverso la comprensione delle seguenti fatti:

  • '() è una raccolta (un elenco persistente), non è una sequenza. Tuttavia è sequenziale, quindi è possibile chiamare seq su di esso per convertirlo in sequenza.
  • zero rappresenta la sequenza vuota - quindi quindi (seq '()) restituisce nil, come fa (seq (rest '()))
  • first ritorna nil su una sequenza vuota - quindi perché (first (rest '())) è nullo.
Problemi correlati