【问题标题】:How to parse nested parameters in a Clojure defn?如何解析 Clojure defn 中的嵌套参数?
【发布时间】:2017-04-22 15:59:31
【问题描述】:

我在浏览一些Clojure source code 时遇到了这个功能:

(defn draw-mask [app-state [r c]]
  (let [x1 (+ 25 (* c 50))
        y1 (+ 25 (* r 50))]
    [:circle {:cx x1 :cy y1 :r 12 :fill "white"}]))

我不明白[app-state [r c]] 是如何解析的。一个典型的数据结构将传递给它什么以及 defn 如何将其打包出来。 clojure 文档中对此的任何引用将不胜感激,尤其是因为 ClojureDocs.org was of no help on the subject

【问题讨论】:

  • Iirc,所有破坏都使用deconstruct(或类似的东西)宏。它只是将其转换为对列表的firstrestnth 的调用,以及对地图访问器的委托。只是典型的宏“魔法”。
  • 这个词是“解构”——使用它应该可以帮助您找到好的文档,例如clojure.org/guides/destructuring
  • ...坦率地说,我认为描述解构的工作原理一般(我是这么读的)范围太广,不能成为一个好的 StackOverflow 问题——如果您查看上面链接的解构页面,则内容比答案所能合理涵盖的要多得多!

标签: clojure


【解决方案1】:

更正

正如@Josh 指出的那样,顺序解构需要nth 才能工作:seqability 是不够的。


这是sequential destructuring 的简单案例。让我们使用一个函数来显示正在发生的事情:

(defn foo [app-state [r c]]
 {:app-state app-state, :r r, :c c})
  • 第一个参数app-state 可以是任何值。
  • 第二个参数[r c] 必须类似于一个序列 nth 适用于。然后
    • r 是它的 first 元素,并且
    • c 是第二个。
  • 如果序列不够长,则会产生nil

例子:

(foo 1 ())
;{:app-state 1, :r nil, :c nil}

(foo inc "hello, world!")
;{:app-state #<core$inc clojure.core$inc@32d23c2f>, :r \h, :c \e}

(foo :one [:two :three :four])
;{:app-state :one, :r :two, :c :three}

(foo  "Flubalub" (drop 5 (iterate #(* 10 %) 1)))
;{:app-state "Flubalub", :r 100000, :c 1000000}

但是

(foo 99 #{1 2})
;java.lang.UnsupportedOperationException: nth not supported on this type: PersistentHashSet
; ...

【讨论】:

    【解决方案2】:

    您示例中的函数draw-mask 有两个参数。第一个是app-state,它没有在您的代码中使用,第二个可以是几种不同类型的数据之一:来自映射、字符串、列表或最常见的向量的值。您可以在clojure code 中看到nthFrom 中可以使用的不同类型。

    这称为顺序destructuring,正如上面提到的其他 cmets,这是一个很大的话题。但是,对于您的情况,它是这样工作的:

    (draw-mask xyz [3 9])     ---> In draw-mask, r is 3, and c is 9.
    (draw-mask xyz [3])       ---> In draw-mask, r is 3, and c is nil.
    (draw-mask xyz [3 9 12])  ---> In draw-mask, r is 3, and c is 9 -- 12 is not bound
    

    这里需要澄清一点:结构是否为seqable? 并不是能够被解构的主要标准。例如,setseqable?,但不能解构。 顺序解构(不同于关联解构,使用map,这里不讨论)的主要标准是必须支持nth。在RT.java 中,您将看到可能类型的列表。它们是:CharSequence,一个原生 Java 数组,RandomAccessMatcherMap.EntrySequentialSequential 将涵盖最常见的结构:列表和向量)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-04
      • 1970-01-01
      • 1970-01-01
      • 2010-11-14
      • 2017-10-09
      • 2011-05-26
      • 2021-12-17
      • 2019-01-21
      相关资源
      最近更新 更多