Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure 解构映射参数:键与老式let_Clojure - Fatal编程技术网

Clojure 解构映射参数:键与老式let

Clojure 解构映射参数:键与老式let,clojure,Clojure,从Scheme的背景中学习Clojure,我的直觉是编写如下代码: (defn my-func [data] (let [right (:right data) left (:left data)] ... body ... )) 然而,我很快就被告知模式匹配是Clojure(或者说Haskell和Scala)的一个重要特性,因此我觉得不得不写: (defn my-func [ {:keys [right left] } ] ... body ...)

从Scheme的背景中学习Clojure,我的直觉是编写如下代码:

(defn my-func [data]
  (let [right (:right data)
        left  (:left data)]
     ... body ... ))
然而,我很快就被告知模式匹配是Clojure(或者说Haskell和Scala)的一个重要特性,因此我觉得不得不写:

(defn my-func [ {:keys [right left] } ]
   ... body ...)
所以我的代码现在充斥着这种语法。不知怎么的,我不喜欢它。我发现我的代码不太吸引人,可读性可能更低(但这可能是因为缺乏习惯性Clojure的经验,所以随着时间的推移,它会变得更好)


所以我想问,是否有一个基本的理由使用一种风格而不是另一种?例如,编译器生成的字节码在第二种情况下效率要高得多。或者我还应该知道其他原因吗?

键的解构只是一种语法糖,实际上扩展为一系列调用
get
和符号赋值。例如:

(macroexpand-1
  '(let [{:keys [a b]} {:a 1 :b 2}]))
扩展为:

(let*
 [map__2507
  {:a 1, :b 2}
  map__2507
  (if (clojure.core/seq? map__2507) (clojure.lang.PersistentHashMap/create (clojure.core/seq map__2507)) map__2507)
  a
  (clojure.core/get map__2507 :a)
  b
  (clojure.core/get map__2507 :b)])
解构的主要目标(请注意,它只是解构,而不是完全模式匹配)是简洁的代码,不涉及性能优化

要说明没有
:keys
解构的代码是如何更加详细,请看一个示例:

(let [{:keys [id name address age salary]} person]
  ...)
vs


:keys
解构只是一种语法糖,实际上扩展为对
get
的一系列调用和对符号的赋值。例如:

(macroexpand-1
  '(let [{:keys [a b]} {:a 1 :b 2}]))
扩展为:

(let*
 [map__2507
  {:a 1, :b 2}
  map__2507
  (if (clojure.core/seq? map__2507) (clojure.lang.PersistentHashMap/create (clojure.core/seq map__2507)) map__2507)
  a
  (clojure.core/get map__2507 :a)
  b
  (clojure.core/get map__2507 :b)])
解构的主要目标(请注意,它只是解构,而不是完全模式匹配)是简洁的代码,不涉及性能优化

要说明没有
:keys
解构的代码是如何更加详细,请看一个示例:

(let [{:keys [id name address age salary]} person]
  ...)
vs

当你写这篇文章时:

(defn my-func [{:keys [right left]}]
  ,,,)
与此相同:

(defn my-func [data]
  (let [{:keys [right left]} data]
    ,,,))
(defn my-func [data]
  (let [right (:right data)
        left (:left data)]
    ,,,))
与此相同:

(defn my-func [data]
  (let [{:keys [right left]} data]
    ,,,))
(defn my-func [data]
  (let [right (:right data)
        left (:left data)]
    ,,,))
,使用更简洁的形式没有性能优势。然而,还有一个好处:即简洁

,解构键的主要优点是,每个键名只需写一次,而不是两次

,直接在函数的参数向量中进行解构会降低代码的可读性,这就是为什么它在Clojure中并不常见的原因

最棒的是,由于Clojure中的参数命名并没有完成解构,因此您可以在这两个方面都做到最好(我上面给出的第二种形式):

这样,您既可以获得可读性(尤其是如果您将参数命名为比
数据更好的名称),又可以获得简洁性(通过使用
:键
解构)。

编写此文件时:

(defn my-func [{:keys [right left]}]
  ,,,)
与此相同:

(defn my-func [data]
  (let [{:keys [right left]} data]
    ,,,))
(defn my-func [data]
  (let [right (:right data)
        left (:left data)]
    ,,,))
与此相同:

(defn my-func [data]
  (let [{:keys [right left]} data]
    ,,,))
(defn my-func [data]
  (let [right (:right data)
        left (:left data)]
    ,,,))
,使用更简洁的形式没有性能优势。然而,还有一个好处:即简洁

,解构键的主要优点是,每个键名只需写一次,而不是两次

,直接在函数的参数向量中进行解构会降低代码的可读性,这就是为什么它在Clojure中并不常见的原因

最棒的是,由于Clojure中的参数命名并没有完成解构,因此您可以在这两个方面都做到最好(我上面给出的第二种形式):


通过这种方式,您既可以获得可读性(尤其是如果您将参数命名为优于
数据的名称),也可以获得简洁性(通过使用
:keys
解构)。

为了完整性,这来自Clojure:

惯用代码经常使用解构。但是,如果要将子结构作为调用方协定的一部分进行通信,则只应在arg列表中进行分解。否则,在第一线let中进行解构。示例:从书中可以看出,该测试失败,在arg列表中进行了太多的解构


为了完整起见,这来自Clojure:

惯用代码经常使用解构。但是,如果要将子结构作为调用方协定的一部分进行通信,则只应在arg列表中进行分解。否则,在第一线let中进行解构。示例:从书中可以看出,该测试失败,在arg列表中进行了太多的解构


正如Piotrek所提到的,最大的好处是您不需要重复每个名称两次(例如,符号“right”和关键字“:right”),并且符号“data”从每行以及arg列表中删除。感谢Piotrek/AlanAs Piotrek所提到的这么多,最大的好处是您不需要重复每个名称两次(例如,符号“right”)和关键字“:right”),并且符号“data”从每行以及arg列表中删除。非常感谢Piotrek/Alan非常感谢Sam!也谢谢你提供的关于分解v模式匹配的参考资料非常感谢Sam!也谢谢你提供的关于v模式匹配的参考资料非常感谢你,瓦伦丁!非常感谢你,瓦伦丁!