2009-03-26 6 views
15

Я смотрю отличный учебник Clojure here. В одном из примеров он имеет Clojure код по следующим направлениям:Почему "(def vowel? (Set" aeiou "))" Работаете?

(def vowel? (set "aeiou")) 

Это делает гласный возвращает истину для гласных и согласных ложно для:

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

Почему это? Я предполагаю, что это имеет какое-то отношение к знаку вопроса за именем переменной. Не удалось найти что-либо сразу же в учебнике ...


Редактировать Я просто понял, vowel? не возвращается истинным или ложным, а сам элемент или ноль. См. Мой собственный ответ.

ответ

16

Это совершенно аналогично тому, как работают карты (самые естественные объекты в Clojure). Когда карта называется функция, она работает как отображение:

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

Так что имеет смысл, что множество Clojure можно назвать функцией, и будет работать в качестве теста членства. Кстати, если вы используете ключевые слова (те вещи, которые начинаются с двоеточия) в качестве ключей отображения, они работают также как аналогичные функции, так что вы можете сделать

user=> (:bar ob) 
:baz 

и даже то же самое с наборами Ключевые слова:

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

Но, опять же, этот последний трюк работает только с ключевыми словами, а не что-нибудь другое, что вы могли бы использовать в качестве ключей в отображении или членов в наборе.

7

Aha! В итоге я понял это. Он фактически не возвращает true или false, скорее он возвращает первое вхождение в наборе, или nil, если оно не встречается.

И потому, что вы можете использовать это как условие (nil обрабатывается как false и non-nil как true), это работает как хороший маленький взлом для проверки того, содержит ли строка букву.

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

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

Звучит прямо для меня. Значок вопроса указывает, что он может использоваться в качестве теста. Вы часто увидите восклицательный знак о функциях, которые имеют побочные эффекты. Они не являются частью языка, они - настоящие традиции (так что вы знаете безопасные функции от «опасных»). – MBCook

+2

Чтобы было ясно,? а также ! являются просто символами типа a и b, и вы можете использовать их для обозначения символов (как \, /, *, -, + ...). Существуют традиции для обозначения определенных символов в Лиспе, но между диалектами существуют небольшие различия. – Svante

+0

ах, спасибо @svante! Я думал, что есть что-то волшебное о «?» :) – Epaga