Clojure 位置破坏函数
我是clojure的新手,我试图尽可能多地理解,但是文档太模糊了 当你有一个函数Clojure 位置破坏函数,clojure,defn,Clojure,Defn,我是clojure的新手,我试图尽可能多地理解,但是文档太模糊了 当你有一个函数 (fn [_ {:keys [kind]}] kind) 我的理解是,该函数接受向量映射,但只希望访问第二个参数{:keys…..指定的键,对吗 那么我要传递多少个参数给这个函数?1还是2 它是一个向量吗?{:kind 1:dog 2}还是向量键值(:kind{…})在repl中尝试一个给定的函数语法,可以很容易地看到它的作用 +user=> ((fn [_ {:keys [kind]}] kind) (:
(fn [_ {:keys [kind]}] kind)
我的理解是,该函数接受向量映射,但只希望访问第二个参数{:keys…..
指定的键,对吗
那么我要传递多少个参数给这个函数?1还是2
它是一个向量吗?{:kind 1:dog 2}还是向量键值(:kind{…})在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[]}
解构语法是,并描述了绑定来自hashmap的值的简写形式。在Clojure{}
中,是一个hashmap,[]
是一个向量,它们是不可互换的。(:foo m)
调用get
在m
中查找键:foo
下的值(让[{:keys[foo]}{:foo“bar”}]…)
和(让[foo(:foo{:foo“bar”)相等)。
您的函数需要两个参数(具有arity 2)。第一个参数的名称是
(下划线,)它通常表示一个未使用的变量。(它是一个有效的变量名,并且被绑定,但按照惯例它未被使用,所以它表示一个占位符。)
第二个参数是destructured-{:keys[kind]}
,这意味着期望值是一个映射,并且作为解构的结果,名为kind
的变量将绑定到实际参数的key:kind
的值(如果没有这样的键,则为nil)
因此,您的函数需要两个参数,第一个参数被忽略,第二个参数必须是带有键:kind
(也可以是其他键,但它们被忽略)的映射
另外,我又看了一遍你的问题,我意识到你的困惑可能来自哪里看起来像是在第二个位置包含一个映射的向量。这是正确的,但并非在Clojure中的所有位置。向量表示法意味着您可以将向量粘贴在那里。Clojure用户使用方括号表示函数的形式参数列表-这是Clojure中的常见模式的一部分,即在序列的所有位置使用向量文本ected。事实上,与其他LISP相比,它非常方便,因为在其他LISP中,您需要在许多地方小心地使用引号,以避免将列表解释为函数应用程序表单。但这是一个离题,重要的一点在于
fn
(和defn
)方括号表示参数列表,并不意味着参数是一个向量。让我们为函数命名:
(defn splot [_ {:keys [kind]}] kind)
这是英语的简写
(defn splot [_ {kind :kind}] kind)
- 两个(位置)参数的函数:
,通常未使用,以及- 一个匿名映射,其
条目绑定到local:kind
kind
- 然后返回绑定到
的内容kind
nil
例如:
(splot "..." 6) ;nil
(splot "..." {}) ;nil
(splot "..." {:kind 77}) ;77
我不知道我是否会直截了当地说。如果你已经知道答案是什么,那么很容易验证,但如果你不知道,你只是在随机猜测,希望其中一个是合法的。例如,在repl:
(fn[{{[xy]:sam}:top:keys[z]}[{:strs[a]}{b2}]]nil中尝试一下这个方法
-记住,您只允许在repl中尝试它,而不是通过检查解构表单来分析它。我对这个答案感到困惑“\uu,传统上未使用”如果它是按惯例使用的,那么为什么我们有它……为什么不只使用一个参数呢?是否有一些文档可以解释构造这样的函数?以及它背后的目的?@Kendall明白。一般来说,这个问题可能值得问。@Kendall你永远不会“孤立地”定义一个没有使用参数的函数,但通常您必须定义一个参数列表与其他接口匹配的函数,因为您将函数作为参数传递给其他函数,该函数使用两个参数调用您的函数是一个有点奇怪的表达式,但它显示了您可能会在其中执行此操作的场景。
(splot "..." 6) ;nil
(splot "..." {}) ;nil
(splot "..." {:kind 77}) ;77