`

clojure解构(clojure destructuring)

阅读更多
解构是什么?
可以认为map、list、struct等是构造出来数据结构。怎么取这些结构里面的数据?那就需要把结构拆开,取到数据。这就是解构(destructuring)。

为什么要解构?
由于在clojure中如果只靠一些集合到操作函数如first、last、nth等函数,不能够简洁的获取一些嵌套集合中的元素,所以需要destructuring来使我们可以简洁快速的去获取集合中的元素。

clojure中的解构
clojure支持的结构有:有顺序集合(sequential collection)的解构和map的解构。

一、Sequential destructuring

有序集合包括:
    clojure的list,vector以及sequence。
    所有实现java.util.List接口的集合
    java数组
    字符串

1、根据位置对应来解构
(def v [42 "foo" 99.2 [5 12]])
(let [[x y z] v]
  (+ x z))
;= 141.2

;;使用下划线占位
(let [[x _ _ [y z]] v] 
  (+ x y z))
;= 59

2、收集剩余的元素(Gathering extra-positional sequential values)
;;使用&来收集
(let [[x & rest] v] 
  rest)
;= ("foo" 99.2 [5 12])

3、保留解构的值(retaining the destructured value)
;;使用as来保留解构的值
(let [[x _ z :as original-vector] v] 
  (conj original-vector (+ x z)))
;= [42 "foo" 99.2 [5 12] 141.2]


二、Map destructuring

可以进行map解构的类型有:
  clojure hash-map,array-map,record。
  所有实现java.util.Map接口的集合
  支持get函数获取相应值的对象,如:clojure vector,string,array
 
1、位置对应来解构
(def m {:a 5 :b 6 
        :c [7 8 9] 
        :d {:e 10 :f 11}
        "foo" 88
        42 false})
;;注意:这里key不单是:key类型,也可以是其他类型
(let [{a :a b :b} m] 
  (+ a b))
;= 11

;;注意:如果是数组、字符串或vector,解构的key是下标
(let [{x 3 y 8} [12 0 0 -18 44 6 0 0 1]] 
  (+ x y))
;= -17

;;顺序解构和map解构混合
(let [{[x _ y] :c} m] 
  (+ x y))
;= 16

(def map-in-vector ["James" {:birthday (java.util.Date. 73 1 6)}])
;= #'user/map-in-vector

(let [[name {bd :birthday}] map-in-vector]
  (str name " was born on " bd))
;= "James was born on Thu Feb 06 00:00:00 EST 1973"

2、保留解构的值(retaining the destructured value)
和顺序解构一样用as来保存。
(let [{r1 :x r2 :y :as randoms}
       (zipmap [:x :y :z] (repeatedly (partial rand-int 10)))]
(assoc randoms :sum (+ r1 r2)))
;= {:sum 17, :z 3, :y 8, :x 9}

3、默认值(Default values)
(let [k :unkown x :a 
       :or {k 50}
       m]
  (+ k x))
;;= 55     

4、绑定值到对应的key上(binding values to their key‘s name)
;;这里的可以用:keys、:strs、:syms来指定key的类型
;;但是通常使用:keys类型
;;在很多框架中,经常会看到:keys,:or,:as的组合使用
(def chas {:name "Chas" :age 31 :location "Massachusetts"}) 
(let [{name :name age :age location :location} chas]
  (format "%s is %s years old and lives in %s." name age location)) 
;= "Chas is 31 years old and lives in Massachusetts."

5、对剩余部分像map一样解构(Destructuring rest sequences as map key/value pairs)
;;这个代码太乱,有洁癖的人受不鸟
(def user-info ["robert8990" 2011 :name "Bob" :city "Boston"])
(let [[username account-year & extra-info] user-info
       {:keys [name city]} (apply hash-map extra-info)] 
  (format "%s is in %s" name city))
;= "Bob is in Boston"

;;如果剩余部分的参数个数是偶数个的话,可以用map解构
;;有洁癖的人现在觉得世界清静多了
(let [[username account-year & {:keys [name city]}] user-info] 
  (format "%s is in %s" name city))
;= "Bob is in Boston"


最后,虽然以上的例子只是用let,但是解构用在fn、defn等地方都是可以的。
(defn foo [{:keys [name age ] :as opts}] 
  (println name ":" age ))
;;异常
(foo :name "hello" :age 20)
;=ArityException Wrong number of args (4) passed to: core$foo  clojure.lang.AFn.throwArity (AFn.java:437)
;;正常
(foo {:name "hello" :age 20})
;=hello : 20

(defn foo2 [& {:keys [name age] 
                      :or {name "peter" age "18"} 
                      :as opts}] 
  (println name ":" age))
;;异常
(foo2 {:name "hello" :age 20})
;;=IllegalArgumentException No value supplied for key: ......
;;正常
(foo2)
;;=peter : 18
(foo2 :name "peter2" :age 20)
;;=peter2 : 20

利用这个可以写出的DSL风格的代码可读性会很好。
分享到:
评论

相关推荐

    Clojure电子书合集1(12本)

    [2009] Programming Clojure.(Stuart Halloway).[1934356336].pdf [2010] Functional Programming with Clojure - Simple Concurrency on the JVM.(Tim Berglund, Matthew McCullough).[193650202X].pdf [2010] ...

    Clojure入门教程- Clojure – Functional Programming for the JVM中文版

    ### Clojure入门教程知识点概述 #### 一、Clojure简介 - **Clojure**是一种运行在Java虚拟机(JVM)上的动态编程语言,它继承了Lisp家族的强大功能,同时结合了现代编程语言的优点,如面向对象编程和函数式编程。 ##...

    Clojure编程乐趣]+clojure_programming.pdf

    Clojure是一种基于Lisp家族的函数式编程语言,它运行在Java虚拟机(JVM)上,同时也支持JavaScript和其他平台。Clojure的设计目标是提供一个高效、并发、可移植的环境,适合解决现代软件开发中的复杂问题。在这个...

    Practical Clojure.pdf

    根据提供的文件内容,我们可以提取出以下关于Clojure语言的知识点: Clojure是一种编程语言,它给作者留下了深刻的印象,并且被视为一种多用途的、全面的编程语言。作者在开始学习Clojure时,体会到了编程的乐趣,...

    Clojure电子书合集2(13本)

    [2013] Functional Programming Patterns in Scala and Clojure - Write Lean Programs for the JVM.(Michael Bevilacqua-Linn).[1937785475].pdf+epub.rar [2014] Clojure Cookbook - Recipes for Functional ...

    Programming Clojure 英文电子版

    ### 编程Clojure:全面解析与学习指南 #### 一、Clojure语言概述 《Programming Clojure》是一本深入探讨Clojure编程语言的书籍,该书由Stuart Halloway编写,出版于2009年3月,由Pragmatic Bookshelf出版社发行。...

    clojure1.3.0及资料

    Clojure是一种基于Lisp的函数式编程语言,它运行在Java虚拟机(JVM)上,充分利用了Java的生态系统。Clojure的设计目标是提供一种静态类型的、并发的、内存安全的语言,同时保持Lisp的简洁性和灵活性。在这个压缩包...

    clojure电子书

    《Clojure电子书》集合包含了三本关于Clojure编程的重要书籍和一个Leiningen的Windows安装程序,这对于学习和深入理解Clojure语言至关重要。Clojure是一种基于Lisp的函数式编程语言,它运行在Java虚拟机(JVM)上,...

    Professional.Clojure.1119267277

    Clear, practical Clojure for the professional programmer Professional Clojure is the experienced developer's guide to functional programming using the Clojure language. Designed specifically to meet ...

    programming-clojure-3rd

    《Programming Clojure 第三版》是一本深入探讨Clojure编程语言的专业书籍,旨在帮助开发者全面理解和掌握这门基于Lisp的现代函数式编程语言。Clojure是由Rich Hickey设计的,它运行在Java虚拟机(JVM)上,同时也...

    Clojure Data Analysis Cookbook

    ### Clojure 数据分析实战指南 #### 一、书籍概述与背景 《Clojure 数据分析实战指南》是一本针对数据分析师和技术开发人员的实用手册。本书由 Eric Rochester 编写,旨在帮助读者通过超过110个实用案例深入了解...

    Clojure可选类型系统TypedClojure.zip

    Typed Clojure 保留了 Clojure 的优势,是 Clojure 的可选类型系统,也可以说是 Clojure 的一个库,改善了大量的静态类型安全检测。主要特性:从 Java 中保护你的 Clojure 程序,进行安全的互操作,正确的使用外部 ...

    Lacinia纯Clojure实现的GraphQL

    【Lacinia:纯Clojure实现的GraphQL解析器】 在当今的Web开发中,GraphQL作为一种强大的数据查询语言,已经越来越受到开发者的欢迎。它提供了一种高效、灵活的方式来获取API数据,允许客户端指定他们需要什么数据,...

    Clojure Handbook(2012.11.1)

    Clojure是一种现代的Lisp方言,运行在Java虚拟机(JVM)上。作为一种函数式编程语言,它被设计为一种既高效又表达力强的工具,用于解决并发问题。Clojure Handbook是一份关于Clojure编程语言的学习笔记,旨在为读者...

    Mastering.Clojure.1785

    Learn to handle data using sequences, reducers, and transducers in Clojure Explore the lesser known and more advanced features, constructs, and methodologies of the Clojure language and its ecosystem,...

Global site tag (gtag.js) - Google Analytics