2010-06-25 12 views
22

Quiero escribir una función que devuelva el valor booleano verdadero si la colección dada no está vacía y de lo contrario es falsa.¿Cuál es la forma correcta de "clojure" para verificar si una colección no está vacía?

Yo tampoco podía hacer

defn .. 
(boolean (seq coll)) 

o

defn .. 
(not (empty? coll)) 

Como soy nuevo en clojure principio estaba inclinado a ir con # 2 (más legible), pero la referencia clojure API para empty? dice explícitamente usar la expresión idiomática (seq coll) en lugar de (not (empty? coll)), tal vez para evitar la doble negación.

Quiero saber cuál es la forma clojure de comprobar si una colección no está vacía y devolver un booleano verdadero/falso.

Respuesta

12

El paso de la cadena de documentación empty? 's lo que usted ha mencionado significa en particular que tal función nonempty? Nunca debería ser necesario, o incluso particularmente útil, porque seq siempre puede sustituir a la que en contextos de Boole, que a su código de Clojure pura poder.

Sin embargo, si se siente obligado a escribir una función de este tipo, diré que me gusta más el primer acercamiento. empty? está construido en seq de todos modos, por lo que no hay forma de evitar llamarlo; simplemente lanzar el resultado a Boolean parece más limpio que dos viajes a través de not. Para otras opciones, vea p. nil?, false? (todavía prefiero el elenco).

Por cierto, ¿por qué quieres escribir esto ...? Para llamar a un método de Java con un argumento boolean tal vez? En ese caso, creo que el elenco expresaría la intención muy bien.

Actualización: un ejemplo para ilustrar este último punto:

  1. Una simple clase Java:

    public class Foo { 
        public static boolean foo(boolean arg) { 
        return !arg; 
        } 
    } 
    
  2. Algunos código de cliente Clojure:

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

De hecho, podríamos' (defalias truthy? Boolean) '. –

4

Además de una excelente respuesta de Michal Marczyk, voy a señalar que hay una función no-vacío específica:

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

pero no hace exactamente lo que pides. (Aunque funcionará en la mayoría de las situaciones).

No vacío devuelve nulo si la colección está vacía y la propia colección si la colección no está vacía. Para pruebas de predicados, eso funcionará bien. Si realmente necesita valores verdaderos y falsos, entonces (no (vacío? X)) es lo que busca.

+6

Usar nombres no vacíos para predicados es tonto. En contextos de predicados, no vacío es solo una versión detallada y lenta de seq. El uso real de no-vacío es cuando se quiere 'dejar 'un local mientras se prueba el vacío, sin destruir la información del tipo tomando una vista secuencial:' (if-let [coll (coll no vacío)] ...) '. Si coll es un mapa, por ejemplo, esto permite probar el vacío sin convertir a seq. – amalloy

+2

@amalloy 'not-empty' es más legible, menos de bajo nivel y luego' seq', y tiene exactamente la misma velocidad, como puede ver mirando su fuente en https://github.com/clojure/clojure/blob /clojure-1.7.0/src/clj/clojure/core.clj#L5302 – alesguzik

26

De acuerdo con la alegría de Clojure, nula juego de palabras conseq es idiomático:

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

" ... el uso de seq como una condición de terminación es la forma idiomática para probar si una secuencia está vacía. Si probamos [en el ejemplo anterior] solo s en lugar de (seq s), entonces la condición de terminación no ocurriría incluso para colecciones vacías ... "

Cuestiones relacionadas