2010-06-25 14 views
22

Voglio scrivere una funzione che restituisca il valore booleano true se la raccolta data non è vuota e false altrimenti.Qual è il corretto "modo clojure" per verificare se una raccolta non è vuota

Potevo fare

defn .. 
(boolean (seq coll)) 

o

defn .. 
(not (empty? coll)) 

Come io sono nuovo di clojure Inizialmente ero propenso ad andare con 2 # (più leggibile), ma il riferimento clojure API per empty? dice esplicitamente usare l'espressione (seq coll) anziché (not (empty? coll)), forse per evitare la doppia negazione.

Desidero sapere qual è il modo di clandestino per verificare se una raccolta non è vuota e restituire un valore booleano vero/falso.

risposta

12

Il passaggio da docstring empty? s', che lei ha citato i mezzi, in particolare, che tale funzione nonempty? dovrebbe mai essere necessario, o anche particolarmente utile, perché seq può sempre sostituire in contesti booleani, che nel codice Clojure puro esso può.

Se ti senti obbligato a scrivere comunque una tale funzione, dirò che mi piace il primo approccio migliore. empty? è costruito su seq in ogni caso, quindi non si può evitare di chiamarlo; il solo casting del risultato su Boolean sembra più pulito di due viaggi tramite not. Per altre opzioni, vedi ad es. nil?, false? (preferisco ancora il cast).

Per inciso, perché vuoi scrivere questo ...? Per chiamare un metodo Java con un argomento boolean forse? In tal caso, penso che il cast esprimerebbe bene l'intenzione.

Aggiornamento: un esempio per illustrare quest'ultimo punto:

  1. Una semplice classe Java:

    public class Foo { 
        public static boolean foo(boolean arg) { 
        return !arg; 
        } 
    } 
    
  2. Alcuni Clojure codice client:

    (Foo/foo nil) 
    ; => NullPointerException 
    (Foo/foo (boolean nil)) 
    ; => true 
    
+6

In effetti, potremmo' (defalias truthy? Boolean) '. –

4

Oltre alla risposta eccellente di Michal Marczyk, mi fanno notare che non v'è una specifica funzione non-vuoto:

http://clojure.github.io/clojure/clojure.core-api.html#clojure.core/not-empty

ma non fa esattamente quello che chiedete. (Anche se funzionerà nella maggior parte delle situazioni).

Non vuoto restituisce nil se la raccolta è vuota e la raccolta stessa se la raccolta non è vuota. Per i test preliminari, ciò funzionerà bene. Se hai effettivamente bisogno di valori veri e falsi, allora (non (vuoto? X)) è ciò che stai cercando.

+6

L'uso di non vuoto per i predicati è sciocco. Nei contesti dei predicati, non-vuoto è solo una versione prolissa e dettagliata di seq. Il vero uso del non vuoto è quando si vuole "lasciare" un locale mentre si prova per il vuoto, senza distruggere le informazioni sul tipo prendendo una vista sequenziale: "(if-let [coll (non-vuoto coll)] ...) '. Se coll è una mappa, ad esempio, questo ti permette di verificare la presenza di vuoto senza convertire in seq. – amalloy

+2

@amalloy 'not-empty' è più leggibile, meno di basso livello quindi' seq' e ha esattamente la stessa velocità, come si può vedere guardando la sua origine su https://github.com/clojure/clojure/blob /clojure-1.7.0/src/clj/clojure/core.clj#L5302 – alesguzik

26

Secondo gioia di Clojure, nil punning con seq è idiomatica:

(defn print-seq [s] 
    (when (seq s) 
    (prn (first s)) 
    (recur (rest s)))) 

" ... l'uso di seq come condizione di terminazione è il modo idiomatica per verificare se una sequenza è vuota. Se abbiamo provato [nell'esempio sopra] solo s anziché (seq s), la condizione di terminazione non si verificherebbe nemmeno per le raccolte vuote ... "

Problemi correlati