【问题标题】:Positional Destructing Functions位置破坏函数
【发布时间】:2016-07-27 05:00:15
【问题描述】:

我是 clojure 的新手,我正在尝试尽可能多地理解,但是文档太模糊了

当你有一个功能时

(fn [_ {:keys [kind]}] kind)

我的理解是该函数采用矢量图,但只想访问第二个参数{:keys..... 指定的键,对吗?

那我要传递多少个参数给这个函数呢? 1 还是 2?

它是一个向量吗? {:kind 1 :dog 2} 还是向量键值 (:kind {....})?

【问题讨论】:

    标签: clojure defn


    【解决方案1】:

    您的函数需要两个参数(有 2 个参数)。第一个参数的名称是 _(下划线),通常表示未使用的变量。 (它是一个有效的变量名,它会被绑定,但按照约定不使用它,所以它表示一个占位符。)

    第二个参数是解构的-{:keys [kind]},表示期望的值是一个map,解构后一个名为kind的变量会绑定到实际参数的key:kind的值(如果没有这样的键,则为零。)

    所以你的函数需要两个参数,第一个被忽略,第二个必须是带有键 :kind 的映射(可能还有其他键,但它们被忽略了。)

    ((fn [_ {:keys [kind]}] kind) :foo {:kind :bar, :color :green})
    => :bar
    

    附:我再次查看了您的问题,我意识到您的困惑可能来自哪里。语法[_ {:kind [kind]}] 看起来像一个在第二个位置包含地图的向量。这是正确的,但在 Clojure 中并非所有地方都使用向量表示法意味着您可以将向量粘贴到那里。 Clojure 用户为函数的形式参数列表使用方括号 - 这是 Clojure 中常见模式的一部分,即在可能需要序列的任何地方都使用向量文字。与其他需要在许多地方小心使用引号以避免将列表解释为函数应用程序表单的 Lisp 相比,它实际上非常方便。不过题外话,重点是fn(和defn)中的方括号表示参数列表,并不表示参数是向量。

    【讨论】:

      【解决方案2】:

      让我们给函数起个名字:

      (defn splot [_ {:keys [kind]}] kind)
      

      这是

      的简写
      (defn splot [_ {kind :kind}] kind)
      
      • 两个(位置)参数的函数:

        1. _,通常未使用,并且
        2. 匿名地图,其:kind 条目绑定到本地kind
      • 然后返回绑定到kind 的任何内容。

      失败的绑定返回nil

      例如:

      (splot "..." 6)            ;nil
      (splot "..." {})           ;nil
      (splot "..." {:kind 77})   ;77
      

      【讨论】:

      • "_, 传统上未使用" 如果传统上使用它,那么我们为什么要拥有它....为什么不只使用一个参数呢?是否有一些文档可以解释构建这样的函数?以及它背后的目的?
      • @Kendall 见here。一般而言,可能值得提出这个问题。
      • @Kendall 您永远不会“孤立地”定义带有未使用参数的函数,但通常您必须定义一个参数列表与其他接口匹配的函数,因为您将函数作为参数传递到其他一些函数,它用两个参数调用你的函数。例如,(map (fn [_ x] [(rand-int 10) x]) (range) xs) 是一个有点奇怪的表达式,但显示了您可能会这样做的场景。
      【解决方案3】:

      通过在 repl 中尝试给定的函数语法,可以很容易地了解它的作用。

      +user=> ((fn [_ {:keys [kind]}] kind) (:kind {}))
      ArityException Wrong number of args (1) passed to: user/eval1/fn--3  clojure.lang.AFn.throwArity (AFn.java:429)
      +user=> ((fn [_ {:keys [kind]}] kind) nil (:kind {}))
      nil
      +user=> ((fn [_ {:keys [kind]}] kind) nil {:kind 1})
      1
      

      {:keys []} 解构语法是described pretty comprehensively in the official docs,它描述了绑定来自哈希映射的值的简写。在 Clojure 中,{} 是一个 hashmap,[] 是一个向量,它们是不可互换的。 (:foo m) 调用 getm 中查找键 :foo 下的值。 (let [{:keys [foo]} {:foo "bar"}] ...)(let [foo (:foo {:foo "bar"})] ...) 是等价的。

      【讨论】:

      • 我不知道我是否会直截了当地说。如果您已经知道答案是很容易验证的,但如果您不知道,您只是在进行随机猜测并希望其中一个是合法的。例如,在 repl 中尝试这个:(fn [{{[x y] :sam} :top :keys [z]} [{:strs [a]} {b 2}]] nil) - 请记住,您只能在 repl 中尝试,不要通过检查解构形式来分析它。
      • 我对这个答案感到困惑
      猜你喜欢
      • 2014-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-12
      • 1970-01-01
      • 2021-06-09
      • 2013-07-17
      • 1970-01-01
      相关资源
      最近更新 更多