2009-03-26 10 views
15

Estoy echando un vistazo al excelente tutorial de Clojure here. En uno de los ejemplos de código que tiene Clojure lo largo de las siguientes líneas:¿por qué "(def vocal? (Set" aeiou ")) funciona?

(def vowel? (set "aeiou")) 

Esto hace que la vocal retorno cierto para las vocales y las consonantes falsa:

(vowel? (first "abc")) ; => true 
(vowel? (first "cba")) ; => false 

¿Por qué es esto? Supongo que tiene algo que ver con el signo de interrogación detrás del nombre de la variable. No se pudo encontrar nada de inmediato en el tutorial ...


Editar Me acabo de dar cuenta vowel? no devuelve verdadero o falso, sino más bien el propio elemento o nula. Ver mi propia respuesta.

Respuesta

16

Esto es perfectamente análogo a cómo funcionan los mapas (los objetos más naturales en Clojure). Cuando el mapa se llama como una función, funciona como una asignación:

user=> (def ob {:foo "bar", :bar :baz, :qwerty 42}) 
#'user/ob 
user=> (ob :foo) 
"bar" 

Así que tiene sentido que un conjunto Clojure puede ser llamado como una función, y funcionará como una prueba de membresía. Por cierto, si utiliza palabras clave (aquellas cosas que empiezan con dos puntos) como las teclas de un mapeo, también trabajan funciones similares, por lo que pueden hacer

user=> (:bar ob) 
:baz 

e incluso lo mismo con conjuntos de palabras clave:

user=> (def vowel-keywords (set [:a :e :i :o :u])) 
#'user/vowel-keywords 
user=> (:a vowel-keywords) 
:a 
user=> (:b vowel-keywords) 
nil 

Pero, de nuevo, este último truco sólo funciona con palabras clave, y no cualquier otra cosa que usted puede usar como claves en un mapeo o miembros de un conjunto.

7

Aha! Terminé descubriendo por mí mismo. En realidad, no devuelve true o false, sino que devuelve la primera aparición en el conjunto, o nula si no se produce.

Y debido a que puede usar esto como una condición (nada se maneja como falso, y no es nulo como verdadero), esto funciona como un pequeño truco para verificar si una cadena contiene una letra.

(vowel? (first "abc")) ; => "a" 
(vowel? (first "cba")) ; => nil 

(if (vowel? (first "abc")) 
     (println "yay") 
     (println "oops")) ; => "yay" 
+0

Me parece correcto. El signo de interrogación indica que se puede usar como prueba. A menudo verá un signo de exclamación sobre las funciones que tienen efectos secundarios. No son parte del idioma, son tradiciones de lisp (para que sepa las funciones seguras de las "peligrosas"). – MBCook

+2

Para que quede claro,? y! son solo caracteres como a y b, y puedes usarlos para nombrar símbolos (como son \, /, *, -, + ...). Existen tradiciones para nombrar ciertos símbolos en Lisp, pero hay pequeñas diferencias entre los dialectos. – Svante

+0

ah, gracias @svante! pensé que había algo mágico sobre el "?" :) – Epaga

Cuestiones relacionadas