函数式编程之clojure(v102)内容摘要:
(do (let [[x y z] val] (println (+ x z))) (let [[x _ _ [y z]] val] (println (+ x y z))) (let [[x amp。 rest] val] (println rest)) (let [[x _ z :as orig] val] (println (conj orig (+ x z)))))。 =。 = 59。 = (foo [5 12])。 = [42 foo [5 12] ]。 = nil 再探 Clojure let amp。 binding (3) • 更多的例子: (def m {:a 5, :b 6, :c [7 8 9], :d {:e 10, :f 11}, foo 88, 42 false}) (do (let [{a :a b :b} m] (println (+ a b))) (let [{f foo} m] (println (+ f 12))) (let [{v 42} m] (println (if v 1 0))) (let [{{e :e} :d} m] (println(* 2 e))) (let [{[x _ y] :c} m] (println (+ x y))))。 = 11。 = 100。 = 0。 = 20。 = 16。 = nil 再探 Clojure let amp。 binding (4) • binding是一个宏,它可以将外部命名与新值绑定,这个新绑定的影响范围为同一线程之内的从此 binding调用开始的调用链。 (def foo 10) (defn printfoo [] (println foo)) (let [foo let foo] (printfoo))。 = 10。 = nil (def ^:dynamic foo 10) (defn printfoo [] (println foo)) (binding [foo bound foo] (printfoo))。 = bound foo。 = nil 再探 Clojure Special form – loop amp。 recur • recur可以在不消耗堆栈空间的情况下将控制转回循环的起始位置,这里的起始位置是指 loop或函数的定义位置。 (loop [x 5] (if (neg? x) x (recur (dec x))))。 =1 (defn countdown [x v] (if (zero? x) (conj v :blastoff!) (do (recur (dec x) (conj v x))))) (countdown 3 [])。 = [3 2 1 :blastoff!] 再探 Clojure Special form – . amp。 new • 所有的与 Java的互操作功能 ——实例化、静态和实例方法调用和字段访问 ——都由 “ .”和“ new”这两个 special form来提供。 再探 Clojure Macro macro允许使用者控制 Clojure编译器,并在一定范围内对语言的规则和句法进行微妙的调整。 Clojure的宏能够让使用者定义他们想要的计算操作集合,并使其能够像语言内建计算操作那样去被使用。 宏,是我们扩展语言的一把利器。 常用的 macro有 : when、 cond、 lazyseq、 delay、 ifnot、and、 or、 ..、 、 、 binding等等。 再探 Clojure Macro语法 (1) 语法 说明 示例 ` 语法引用,用于在宏中引用表达式,作用是延迟表达式的评估。 `(println A)。 = (A) ~ 反语法引用,用在语法引用( `)范围内,作用是标识其中不需要延迟评估的子表达式。 `(println ~(str [1]))。 = ([1]) ~@ 反语法引用拼接,在语法引用( `)范围内,对多个子表达式进行反语法应用。 (let [defs ‗((def x 1) (def y 2))] `(do ~@defs))。 = (do (def x 1) (def y 2)) 再探 Clojure Macro语法 (2) 语法 说明 示例 ~‘ 在语法引用( `)范围内,对本地绑定名进行直译。 `(let [~39。 name ClojureCN] (println ~39。 name))。 = ([name ―ClojureCN‖]。 = ()) ‗~ 在语法引用( `)范围内,代表绑定名称本身。 (defmacro show [v] `(str 39。 ~v : ~v)) (show abc)。 = abc:abc (let [name abc] (show name))。 = name:abc 再探 Clojure Macro示例 (defmacro keywordmap ([] {}) ([coll] `(let [~39。 e ~coll] (reduce conj (map (assoc {} (keyword (str %)) %) (if (coll? ~39。 e) ~39。 e (vector ~39。 e)))))) ([coll amp。 next] `(conj (keywordmap ~coll) (keywordmap ~@next)))) (keywordmap 123 abc [4 5 6] 39。 (x y z) {i j k})。 = {:z z, :y y, :x x, :6 6, :4 4, :5 5, :abc abc, :123 123, :k k, :j j, :i i} 再探 Clojure Sequences (1) 序列抽象定义了一套用来获得和遍历一些数据值上的序列视图的方法。 这些数据要么是一个写集合,要么是一些计算产生的连续的结果。 序列常被叫做“ seqs”,它提供了一些除了基本集合抽象之外几个方法: • seq——可以根据参数生成序列。 • first、 rest和 next提供定位和遍历序列中值的方法。 • lazyseq根据表达式的评估结果生成懒加载序列。 大多数 seq函数都是 lazy的,返回 lazy seq(s)。 再探 Clojure Sequences (2) 可序列化的数据类型(即供 seq函数作为参数的)包括: • 所有的 Clojure集合数据类型。 • 所有的 Java集合数据类型。 • 所有的 Java映射( Map)。 • 所有的 Java字符序列,包括 String类型。 • 所有实现了 Java的 Iterable接口的类型。 • 数组 • nil • 任何实现了 Clojure的。 再探 Clojure Sequences (3) • 操作 seq的一些基本方法: (defn showseq [s] (vector (first s) (second s) (rest s) (next s) (nthrest s 4) (take 4 s) (takelast 4 s) (butlast s) (drop 2 s) (droplast 2 s))) (showseq Clojure)。 = [\C \l (\l \o \j \u \r \e) (\l \o \j \u \r \e) (\u \r \e) (\C \l \o \j) (\j \u \r \e) (\C \l \o \j \u \r) (\o \j \u \r \e) (\C \l \o \j \u)] 再探 Clojure Sequences (4) • 用 seq模仿堆栈( Stack): (conj 39。 () 1 2 3) (peek 39。 (3 2 1)) (pop 39。 (3 2 1)) (conj [] 1 2 3) (peek [1 2 3]) (pop [1 2 3])。 = (3 2 1)。 = 3。 = (2 1)。 = [1 2 3]。 = 3。 = [1 2] 再探 Clojure Sequences (5) • 关于 set: (def lang {java python golang clojure}) (def drink {java chai pop}) (require 39。 [ :as set]) (set/union lang drink)。 = {java clojure chai pop go。函数式编程之clojure(v102)
阅读剩余 0%
本站所有文章资讯、展示的图片素材等内容均为注册用户上传(部分报媒/平媒内容转载自网络合作媒体),仅供学习参考。
用户通过本站上传、发布的任何内容的知识产权归属用户或原始著作权人所有。如有侵犯您的版权,请联系我们反馈本站将在三个工作日内改正。