💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
## 条件处理 `if` 这个special form跟java里面的if的语义是一样的, 它接受三个参数, 第一个是需要判断的条件,第二个表达式是条件成立的时候要执行的表达式,第三个参数是可选的,在条件不成立的时候执行。如果需要执行多个表达式,那么把多个表达式包在do里面。看例子: ``` (import '(java.util Calendar GregorianCalendar)) (let [gc (GregorianCalendar.) day-of-week (.get gc Calendar/DAY_OF_WEEK) is-weekend (or (= day-of-week Calendar/SATURDAY) (= day-of-week Calendar/SUNDAY))] (if is-weekend (println "play") (do (println "work") (println "sleep")))) ``` 宏 `when` 和 `when-not` 提供和if类似的功能, 只是它们只在条件成立(或者不成立)时候执行一个表达式。另一个不同是,你可以执行任意数目的表达式而不用用do把他们包起来。 ``` (when is-weekend (println "play")) (when-not is-weekend (println "work") (println "sleep")) ``` 宏 `if-let` 把一个值bind到一个变量,然后根据这个binding的值来决定到底执行哪个表达式。下面的代码会打印队列里面第一个等待的人的名字,或者打印“no waiting”如果队列里面没有人的话。 ``` (defn process-next [waiting-line] (if-let [name (first waiting-line)] (println name "is next") (println "no waiting"))) (process-next '("Jeremy" "Amanda" "Tami")) ; -> Jeremy is next (process-next '()) ; -> no waiting ``` `when-let` 宏跟 `if-let` 类似, 不同之处跟上面 `if` 和 `when` 的不同之处是类似的。 他们没有else部分,同时还支持执行任意多个表达式。比如: ``` (defn summarize "prints the first item in a collection followed by a period for each remaining item" [coll] ; Execute the when-let body only if the collection isn't empty. (when-let [head (first coll)] (print head) ; Below, dec subtracts one (decrements) from ; the number of items in the collection. (dotimes [_ (dec (count coll))] (print \.)) (println))) (summarize ["Moe" "Larry" "Curly"]) ; -> Moe.. (summarize []) ; -> no output ``` `condp` 宏跟其他语言里面的switch/case语句差不多。它接受两个参数,一个谓词参数 (通常是 `=` 或者 `instance?` ) 以及一个表达式作为第二个参数。在这之后,它接受任意数量的值-表达式的对子,这些对子会按顺序evaluate。如果谓词的条件跟某个值匹配了, 那么对应的表达式就被执行。一个可选的最后一个参数可以指定, 这个参数指定如果一个条件都不符合的话, 那么就返回这个值。如果这个值没有指定,而且没有一个条件符合谓词, 那么一个 `IllegalArgumentException` 异常就会被抛出。 下面的例子让用户输入一个数字,如果用户输入的数字是1,2,3,那么程序会打印这些数字对应的英文单词。否则它会打印”unexpected value”。在那之后,它会测试一个本地binding的类型,如果是个数字它会打印这个数字乘以2的结果;如果是字符串, 那么打印这个字符串的长度乘以2的结果。 ``` (print "Enter a number: ") (flush) ; stays in a buffer otherwise (let [reader (java.io.BufferedReader. *in*) ; stdin line (.readLine reader) value (try (Integer/parseInt line) (catch NumberFormatException e line))] ; use string value if not integer (println (condp = value 1 "one" 2 "two" 3 "three" (str "unexpected value, \"" value \"))) (println (condp instance? value Number (* value 2) String (* (count value) 2)))) ``` `cond` 宏接受任意个 谓词/结果表达式 的组合。它按照顺序来测试所有的谓词,直到有一个谓词的测试结果是true, 那么它返回其所对应的结果。如果没有一个谓词的测试结果是true, 那么会抛出一个 `IllegalArgumentException` 异常。通常最后一个谓词一般都是true, 以充当默认情况。 下面的例子让用户输入水的温度, 然后打印出水的状态: 是冻住了,还是烧开了,还是一般状态。 ``` (print "Enter water temperature in Celsius: ") (flush) (let [reader (java.io.BufferedReader. *in*) line (.readLine reader) temperature (try (Float/parseFloat line) (catch NumberFormatException e line))] ; use string value if not float (println (cond (instance? String temperature) "invalid temperature" (<= temperature 0) "freezing" (>= temperature 100) "boiling" true "neither"))) ```