是 - > Clojure中的运算符(以及在Clojure中调用的运算符是什么?)等效于管道运算符|>在F#?如果是这样,当(|>)被定义为
时,为什么它需要这样一个复杂的宏定义let inline (|>) x f = f x
如果不是,Flo的管道运算符是否存在于Clojure中,或者您如何在Clojure中定义这样的运算符?
答案 0 :(得分:32)
|>
,因为所有函数调用都包含在列表中,例如(+ 1 2)
:你无法做出让1 + 2
孤立地工作的魔力< / EM> 1
->
用于减少嵌套并简化常见模式。例如:
(-> x (assoc :name "ted") (dissoc :size) (keys))
扩展到
(keys (dissoc (assoc x :name "ted") :size))
前者通常更容易阅读,因为从概念上讲,您在x
上执行了一系列操作;以前的代码是“塑造”的,而后者需要一些精神上的解决才能解决问题。
1 你可以编写一个使sorta能够工作的宏。我们的想法是围绕要转换的整个源树包装宏,并让它查找|>
个符号;然后它可以将源转换为您想要的形状。 Hiredman使用functional包以非常Haskell的方式编写代码成为可能。
答案 1 :(得分:11)
它被称为“线程”运算符。由于性能原因,它被编写为宏而不是普通函数,因此它可以提供一个很好的语法 - 即它在编译时应用转换。
它比|&gt;更强大。您描述的运算符,因为它旨在通过多个函数传递值,其中每个连续值都作为以下函数调用的第一个参数“插入”。这是一个有点人为的例子:
(-> [1]
(concat [2 3 4])
(sum)
((fn [x] (+ x 100.0))))
=> 110.0
如果要定义一个与您所描述的F#运算符完全相同的函数,可以执行以下操作:
(defn |> [x f] (f x))
(|> 3 inc)
=> 4
不确定实际有多么有用,但无论如何你仍然存在: - )
最后,如果你想通过一系列函数传递一个值,你总是可以在clojure中执行以下操作:
(defn pipeline [x & fns]
((apply comp fns) x))
(pipeline 1 inc inc inc inc)
=> 5
答案 2 :(得分:10)
答案 3 :(得分:5)
在阅读源代码时(尤其是在说话时),我总是将->
运算符称为“线程优先”,将->>
运算符称为“线程最后”。
请注意,现在有一个运算符as->
比->
或->>.
更灵活。表单为:
(as-> val name (form1 arg1 name arg2)...)
评估值val
并将其分配给占位符符号name
,用户可以将其放置在以下表单中的任何位置。我通常会为占位符符号选择“it”这个词。我们可以像这样模仿线程优先->
:
user=> (-> :a
(vector 1))
[:a 1]
user=> (as-> :a it
(vector it 1) )
[:a 1]
我们可以像这样模仿线程最后->>
:
user=> (->> :a
(vector 2))
[2 :a]
user=> (as-> :a it
(vector 2 it) )
[2 :a]
或者,我们可以将它们组合在一个表达式中:
user=> (as-> :a it
(vector it 1)
(vector 2 it))
[2 [:a 1]]
user=> (as-> :a it
(vector it 1)
(vector 2 it)
(vector "first" it "last"))
["first" [2 [:a 1]] "last"]