Function Functions complement 一个布尔函数的否定返回
1 2 3 (defn identify-humans [social-security-numbers] (filter #(not (vampire? %)) (map vampire-related-details social-security-numbers)))
1 2 3 4 5 (def not-vampire? (complement vampire?)) ;;可以使用complement (defn identify-humans [social-security-numbers] (filter not-vampire? (map vampire-related-details social-security-numbers)))
# 1 2 3 (defn parse "Convert a CSV into rows of columns" [string] (map #(clojure.string/split % #",") (clojure.string/split string #"\n")))
#","
是这个于创建正则表达式字面量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 (ns fwpd.core) (def filename "suspects.csv") (def vamp-keys [:name :glitter-index]) (defn str->int [str] (Integer. str)) (def conversions {:name identity, :glitter-index str->int}) (Defn convert [vamp-key value] ((get conversions vamp-key) value)) (defn parse "Convert a CSV into rows of columns" [string] (map #(clojure.string/split % #",") (clojure.string/split string #"\n"))) (defn mapify "Return a seq of maps like {:name \"Edward Cullen\" :glitter-index 10}" [rows] (map (fn [unmapped-row] (reduce (fn [row-map [vamp-key value]] (assoc row-map vamp-key (convert vamp-key value))) {} (map vector vamp-keys unmapped-row))) rows)) (defn glitter-filter [minimum-glitter records] (filter #(>= (:glitter-index %) minimum-glitter) records)) (glitter-filter 3 (mapify (parse (slurp filename)))) ;; ({:name "Edward Cullen", :glitter-index 10} {:name "Jacob Black", :glitter-index 3} {:name "Carlisle Cullen", :glitter-index 6})
prue function
如果给定相同的参数,则始终返回相同的结果
它不会引起任何副作用(该函数不能进行任何可在函数本身之外观察到的更改)
Living with Immutable Data Structures 不可变的数据结构可确保您的代码不会产生副作用
Recursion Instead of for/while 1 2 3 4 5 6 var wrestlers = getAlligatorWrestlers ();var totalBites = 0 ;var l = wrestlers.length ;for (var i=0 ; i < l; i++){ totalBites += wrestlers[i].timesBitten ; }
对totalBites 会产生副作用,但是是内部的,无害的,没有跟改外部的
但clojure的核心数据结构甚至不允许这些无害的更改
1 2 (def great-baby-name "Rosanthony") great-baby-name ; => "Rosanthony"(let [great-baby-name "Bloodthunder"] great-baby-name); => "Bloodthunder"great-baby-name; => "Rosanthony"
clojure 执行递归使用recur clojure 不提供尾优化
Function Composition Instead of Attribute Mutation 函数组合而不是属性更改
1 2 3 4 5 6 class GlamourShotCaption attr_reader :text def initialize (text )@text = text clean! end private def clean! text.trim! text.gsub!(/lol/ , "LOL" )endendbest = GlamourShotCaption .new("My boa constrictor is so sassy lol! " )best.text ; => "My boa constrictor is so sassy LOL!"
1 2 3 4 (require '[clojure.string :as s]) (defn clean [text] (s/replace (s/trim text) #"lol" "LOL" )) (clean "My boa constrictor is so sassy lol! " )
通过函数组合,而不是属性更改
像这样组合函数(以便将一个函数的返回值作为参数传递给另一个函数)称为函数组合 通常,函数式编程鼓励您通过组合更简单的函数来构建更复杂的函数
一旦您有信心使用不可变数据结构来完成工作,您就会感到更加自信,因为您不必担心哪些肮脏的代码可能会沾上您珍贵的可变变量
comp creating a new function from the composition of any number of functions
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 (def character {:name "Smooches McCutes" :attributes {:intelligence 10 :strength 4 :dexterity 5}}) (def c-int (comp :intelligence :attributes)) (def c-str (comp :strength :attributes)) (def c-dex (comp :dexterity :attributes)) (c-int character); => 10 (c-str character); => 4 (c-dex character); => 5 (fn [c] (:strength (:attributes c))) (defn spell-slots [char] (int (inc (/ (c-int char) 2)))) (def spell-slots-comp (comp int inc #(/ % 2) c-int)) (spell-slots character) ; => 6
1 (defn two-comp [f g] (fn [& args] (f (apply g args))))
memoize 记忆化
(+ 3 (+ 5 8))
1 2 3 4 5 (defn sleepy-identity "Returns the given value after 1 second" [x] (Thread/sleep 1000) x) (sleepy-identity "Mr. Fantastico") ; => "Mr. Fantastico" after 1 second (sleepy-identity "Mr. Fantastico") ; => "Mr. Fantastico" after 1 second
1 2 3 4 (def memo-sleepy-identity (memoize sleepy-identity)) (memo-sleepy-identity "Mr. Fantastico"); => "Mr. Fantastico" after 1 second (memo-sleepy-identity "Mr. Fantastico"); => "Mr. Fantastico" immediately
未完待续……