Clojure的解构是什么意思?

时间:2014-06-29 15:05:23

标签: clojure

我是一个Java和学习clojure。

clojure中究竟是什么解构?

我可以看到this博客说:

  

最简单的解构示例是分配a的值   矢量。

user=> (def point [5 7])
#'user/point

user=> (let [[x y] point]
         (println "x:" x "y:" y))
x: 5 y: 7

assigning the values of a vector的意思是什么?什么是真正的用途?

提前致谢

6 个答案:

答案 0 :(得分:2)

point是一个包含值向量的变量。 [x y]是变量名称的向量。

当您将point分配给[x y]时,解构意味着每个变量都会被赋予值中相应的元素。

这只是一种更简单的写作方式:

(let [x (nth point 0) y (nth point 1)]
    (println "x:" x "y:" y))

有关使用解构的其他方法,请参阅Clojure let binding forms

答案 1 :(得分:2)

术语" Destructuring"声音比它重。

它在视觉上将形状与形状相匹配。例如:

(def nums [1 2 3 4 5 6])

(let [[a b c & others] nums]
  ;; do something
  )

Imagine the effect of the let binding as:

 1  2  3    4 5 6
 |  |  |   (     )
 v  v  v      v
[a  b  c & others]

;; Now we can use a, b, c, others, and of course nums, 
;; inside the let binding:

user=> (let [[a b c & others] nums] 
         (println a) 
         (println b) 
         (println c) 
         (println others) 
         (println nums))      
 1
 2
 3
 (4 5 6)
 [1 2 3 4 5 6]

目标是简明集合的名称项目,以便在let绑定或函数的范围内使用(即在"词法范围内")。

为什么"简洁"?好吧,没有解构,let绑定看起来像这样:

(let [a (nth nums 0) ;; or (first nums)
      b (nth nums 1) ;; or (second nums)
      c (nth nums 2)
      others (drop 3 nums)]
  ;; do something
  )

这说明了基本思想。有许多细节(ifs和buts,dos和don&ts;),值得深入阅读。这里有一些资源可以解释更多,例如:

我个人的最爱:Jay Fields关于Clojure Destructuring的帖子: http://blog.jayfields.com/2010/07/clojure-destructuring.html

Braveclojure对解构的温和介绍: http://www.braveclojure.com/do-things/#3_3_3__Destructuring

答案 2 :(得分:2)

这意味着用符号

制作一些数据结构的图片
((fn [[d [s [_ _]]]] 
  (apply str (concat (take 2 (name d)) (butlast (name s)) (drop 7 (name d))) ))     
   '(describing (structure (of data))))

=> "destructuring"

((fn [[d e _ _ _ _ _ i n g _ _ _ _ _ s t r u c t u r e & etc]] 
  [d e s t r u c t u r i n g]) "describing the structure of data")

=> [\d \e \s \t \r \u \c \t \u \r \i \n \g]

将这些^示例粘贴到REPL&与他们一起玩,看看它是如何运作的。

答案 3 :(得分:0)

解构通过将每个名称绑定到对象的相应部分,将名称模式绑定到复杂对象。

要绑定到序列,您需要提供名称的向量。例如......

(let [[x y] (list 5 7)] ... )

......相当于

(let [x 5, y 7] ... )

要通过索引查找绑定到地图向量,您需要提供名称到密钥的地图 对。例如......

(let [{x 0, y 1} [5 7]] ... )

......相当于上述两种情况。

正如其他人所提到的,你可以找到这个强大机制here的完整描述。

答案 4 :(得分:0)

用于命名数据​​结构的组件,并获取它们的值。

假设你想要一个" person"结构体。在java中,您将一直创建一个包含各种字段的构造函数,getter和setter的类,例如名称,年龄,高度等。

在Clojure中你可以跳过"仪式"并且只是有一个带有3个插槽的向量,首先是名称,而不是年龄,最后是高度。现在你可以简单地命名这些"组件"得到他们的价值观,如下:

(def person ["Fred" 30 180])
(let [[name age height] person]
  (println name age height))    ;; will print: Fred 30 180

p.s - 有更好的方法可以让一个人成为"在clojure中(例如记录等),这只是一个了解解构是什么的例子。

答案 5 :(得分:0)

解构是一种便利功能,它允许通过分离复杂的数据结构( seq-ables ,如矢量或关联)轻松创建局部绑定(而不是变量!)像hash-maps一样),如here所述。

采用以下示例:

(let [v [1 2 3 4 5 6]
      v_0 (first v)
      v_1 (nth v 1)
      v_rest (drop 2 v) 
      m {:a 1 :b 2}
      m_a (get m :a)
      m_b (get m :b)
      m_default (get m :c "DEFAULT")]
  (println v, v_0, v_1, v_rest, m, m_a, m_b, m_default))

然后可以使用如下的解构绑定简化上面的代码:

(let [[v_0 v_1 & v_rest :as v]
      [1 2 3 4 5 6]
      {m_a :a m_b :b m_default :c :or {m_default "DEFAULT"} :as m}
      {:a 1 :b 2}]
  (println v, v_0, v_1, v_rest, m, m_a, m_b, m_default))

解构模式可用于let绑定和函数参数(fndefnletfn等),也可用于宏以返回{{1包含这种解构模式的绑定。

要注意的一个重要用法是使用letif-let宏。始终在整个表单上评估when-let语句,即使结构化绑定本身评估为if

nil