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->
因为我很久没有使用过它了。。。。我很惊讶没有其他人把它作为一个答案提出来