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 在线程宏中使用case时是否可以解构?_Clojure - Fatal编程技术网

Clojure 在线程宏中使用case时是否可以解构?

Clojure 在线程宏中使用case时是否可以解构?,clojure,Clojure,我想在线程宏中包含一个case,这样我就可以根据val的一个键进行分支,这是一个散列映射。这可能吗 编辑:我需要线程val而不是val中的键,因为进一步的函数将需要整个val。基本上,我希望根据val键,分支到threading宏中的函数。但是仍然要向前传递val。考虑在此处使用多方法分派: (def val { :type "bar" }) (-> val (case ??? "bar" "bar type" "baz" "baz type" "other

我想在线程宏中包含一个
case
,这样我就可以根据
val
的一个键进行分支,这是一个散列映射。这可能吗


编辑:我需要线程
val
而不是val中的键,因为进一步的函数将需要整个
val
。基本上,我希望根据
val
键,分支到threading宏中的函数。但是仍然要向前传递
val

考虑在此处使用多方法分派:

(def val { :type "bar" })

(-> val
  (case ???
    "bar" "bar type"
    "baz" "baz type"
    "other type"))

考虑在此处使用多方法分派:

(def val { :type "bar" })

(-> val
  (case ???
    "bar" "bar type"
    "baz" "baz type"
    "other type"))

这似乎是一个有效的例子,可以更好地说明我想做什么:

(defmulti some-operation :type)

(defmethod some-operation "bar"
  [val]
  (println "Bar type!")
  (assoc val :x 42))

(defmethod some-operation "baz"
  [val]
  (println "Baz type!")
  (assoc val :x 100))

(-> {:type "bar"}
    some-operation
    some-other-operation)

这似乎是一个有效的例子,可以更好地说明我想做什么:

(defmulti some-operation :type)

(defmethod some-operation "bar"
  [val]
  (println "Bar type!")
  (assoc val :x 42))

(defmethod some-operation "baz"
  [val]
  (println "Baz type!")
  (assoc val :x 100))

(-> {:type "bar"}
    some-operation
    some-other-operation)

这可以使用
it->
threading宏轻松完成:

要产生期望的结果:

(ns tst.clj.core
  (:use clj.core tupelo.test)
  (:require [tupelo.core :as t] ))
(t/refer-tupelo)

(def val { :type "bar" })

(println "result => "
  (it-> val
    (case (grab :type it)
      "bar" "bar-type"
      "baz" "baz-type"
      "other-type")))
it->
宏在管道的每个阶段将中间值分配给符号
it
。在本例中,我们使用
grab
函数提取
:type
值。它的工作原理类似于
(:键入它)
,但如果找不到键,它将抛出

另一个例子:

result =>  bar-type

这可以使用
it->
threading宏轻松完成:

要产生期望的结果:

(ns tst.clj.core
  (:use clj.core tupelo.test)
  (:require [tupelo.core :as t] ))
(t/refer-tupelo)

(def val { :type "bar" })

(println "result => "
  (it-> val
    (case (grab :type it)
      "bar" "bar-type"
      "baz" "baz-type"
      "other-type")))
it->
宏在管道的每个阶段将中间值分配给符号
it
。在本例中,我们使用
grab
函数提取
:type
值。它的工作原理类似于
(:键入它)
,但如果找不到键,它将抛出

另一个例子:

result =>  bar-type

此外,由于线程宏只需为每个“操作”向seq添加一个项,因此可以轻松使用匿名函数:

(it-> 1
      (inc it)                                  ; thread-first or thread-last
      (+ it 3)                                  ; thread-first
      (/ 10 it)                                 ; thread-last
      (str "We need to order " it " items." )   ; middle of 3 arguments
;=> "We need to order 2 items." )
如果您愿意,还可以编写特殊的宏,重新排列
let
,以便在
->
中使用:

user> (def val { :type "bar" })
#'user/val

user> (-> val
          ((fn [{type :type}]
             (case type
               "bar" "bar type"
               "baz" "baz type"
               "other type"))))
;;=> "bar type"

此外,由于线程宏只需为每个“操作”向seq添加一个项,因此可以轻松使用匿名函数:

(it-> 1
      (inc it)                                  ; thread-first or thread-last
      (+ it 3)                                  ; thread-first
      (/ 10 it)                                 ; thread-last
      (str "We need to order " it " items." )   ; middle of 3 arguments
;=> "We need to order 2 items." )
如果您愿意,还可以编写特殊的宏,重新排列
let
,以便在
->
中使用:

user> (def val { :type "bar" })
#'user/val

user> (-> val
          ((fn [{type :type}]
             (case type
               "bar" "bar type"
               "baz" "baz type"
               "other type"))))
;;=> "bar type"


如果
val
更复杂,您也可以使用
(>val:type(case,,,)
。谢谢@SamEstep——用credit添加了上面的示例。我应该添加我需要
val
,就像下一组fn一样。我会更新这个问题以澄清这一点。我有点不确定该如何表达这个问题,但我想我有一些答案,我将发布这些答案来帮助澄清。@Kris我理解你的问题。我将修改并包含旧信息以供参考如果
val
更复杂,您也可以使用
(>val:type(case,,,)
。谢谢@SamEstep--添加了您的示例,上面添加了Credit,我应该添加我需要
val
,就像下一组fn一样。我会更新这个问题以澄清这一点。我有点不确定该如何表达这个问题,但我想我有一些答案,我将发布这些答案来帮助澄清。@Kris我理解你的问题。我将修改并包含引用的旧信息。啊,我错误地认为您编写的是纯函数。在这种情况下,我想你想要的不是
->
。是什么让它不“纯净”,我没有副作用?我一定是误解了。如果您没有副作用,并且函数总是返回
val
,那么您的函数和
identity
函数之间有什么区别?我想这可能是正切的,但“副作用”不是指函数之外的更改,例如磁盘/网络IO吗?@Kris no;如果函数以调用方可见的方式修改其参数,那么这是一个副作用,函数是不纯净的。啊,我错误地认为您编写的是纯函数。在这种情况下,我想你想要的不是
->
。是什么让它不“纯净”,我没有副作用?我一定是误解了。如果您没有副作用,并且函数总是返回
val
,那么您的函数和
identity
函数之间有什么区别?我想这可能是正切的,但“副作用”不是指函数之外的更改,例如磁盘/网络IO吗?@Kris no;如果函数以调用方可见的方式修改其参数,那么这是一个副作用,函数是不纯净的。它->和之间的区别是什么?它们相似,只是
it->
从Groovy复制了一个好主意,并且总是将线程值命名为
it
。另外,
as->
在定义占位符符号时,我总是觉得有点落后。如果
clojure.core
中的宏与库中的宏之间的差异只是风格上的差异,那么您的答案实际上应该指向
clojure.core
中的宏,并可能在事后提到您的库。实际上,我已经忘记了
as->
,因为我已经很久没有使用它了。。。。我很惊讶没有其他人提到它作为答案。我认为
as->
应该嵌套在
->
中。这解释了为什么占位符是第二个参数。如果它是第一个,您将无法将线程宏嵌套在一起。
it->
和之间有什么区别?它们类似,只是
it->
从Groovy复制了一个好主意,并且总是将线程值命名为
it
。另外,
as->
在定义占位符符号时,我总是觉得有点落后。如果
clojure.core
中的宏与库中的宏之间的差异只是风格上的差异,那么您的答案实际上应该指向
clojure.core
中的宏,并可能在事后提到您的库。实际上,我忘记了
as->
因为我很久没有使用过它了。。。。我很惊讶没有其他人把它作为一个答案提出来