什么是->;你在clojure做什么?
我见过clojure符号->在许多地方使用,但我不确定该符号的名称和作用,甚至不确定它是否是标准clojure的一部分。有人能给我解释一下吗?这叫画眉操作符。这是最好的解释。这是一种从左到右编写代码的方法,而不是从内到外,例如什么是->;你在clojure做什么?,clojure,Clojure,我见过clojure符号->在许多地方使用,但我不确定该符号的名称和作用,甚至不确定它是否是标准clojure的一部分。有人能给我解释一下吗?这叫画眉操作符。这是最好的解释。这是一种从左到右编写代码的方法,而不是从内到外,例如 (reduce (map (map xs bar) foo) baz) 变成 (-> xs (map bar) (map foo) (reduce baz)) 你可能想读源代码,它是 编辑:修复了我对->和->的混淆,多亏了amalloy。遗憾的是,我的示例现在
(reduce (map (map xs bar) foo) baz)
变成
(-> xs (map bar) (map foo) (reduce baz))
你可能想读源代码,它是
编辑:修复了我对
->
和->
的混淆,多亏了amalloy。遗憾的是,我的示例现在不太可能出现在实践中。'->'是一个宏。我认为,最好的描述方式是以“dot特殊形式”为例,其目的是使代码更加简洁易读,正如clojure.org网站对
扩展到:
(. (. System (getProperties)) (get "os.name"))
但更容易书写、阅读和理解。另请参见可以类似使用的->宏:
(-> (System/getProperties) (.get "os.name"))
还有“doto”。假设您有一个对象,希望在该对象上调用多个连续的setter。你可以用doto
(doto person
(.setFName "Joe")
(.setLName "Bob")
(.setHeight [6 2]))
在上面的示例中,setter不返回任何内容,因此“doto”是适当的选择。除非setter返回“this”,否则->不能代替“doto”
这些是与->宏相关的一些技术。我希望这不仅有助于解释它们的作用,而且有助于解释它们存在的原因。->使用函数调用的结果,并按顺序将其发送到下一个函数调用 因此,更简单的例子是:
(-> 2 (+ 3))
返回5,因为它向下一个函数调用(+3)发送2
在这个基础上,
(-> 2
(+ 3)
(- 7))
返回-2。我们保留第一次调用的结果(+3)并将其发送给第二次调用(-7)
正如@bending所指出的,公认的答案是更好地显示doto宏
(doto person
(.setFName "Joe")
(.setLName "Bob")
(.setHeight [6 2]))
我没有完全理解->(画眉或线程)所做的,直到我将其可视化为这样:
(-> expr f1 f2 f3) ;same as (f3 (f2 (f1 expr)))
(-> expr ;same as form above
f1 ;just a different visual layout
f2
f3)
;this form is equivalant and shows the lists for f1, f2, f3.
(-> expr ; expr treaded into first form
(f1 ) ; | result threaded into next form
(f2 ) ; | and so on...
(f3 )) ; V the lists (f1
(f3 (f2 (f1 expr))) ;the result is the same as this
以下是一些例子:
(-> 41 inc dec inc) ;same as (inc (dec (inc 41)))
42
(-> 41 ;same as above but more readable
(inc )
(dec )
(inc ))
42
(inc (dec (inc 41))) ;easier to see equivalence with above form.
42
(-> 4 (* 4 3) (- 6)) ;same as (- (* 4 3 4) 6)
42
(-> 4 ; 4
(* 3 4) ; (* 4 3 4)
(- 6)) ;(- (* 4 3 4) 6)
42
(- (* 4 3 4) 6) ;easier to see equivalence with above form.
42
你可以自己看看:
(macroexpand `(-> 42 inc dec))
我最喜欢Clojure中对画眉操作符的解释:这在一般意义上是正确的,但在细节上是错误的。您已经描述了
->
的行为,而不是->
。您提供的示例将扩展到(reduce(map(map xs bar)foo)baz)
,因为->
通过第二个位置,而不是最后一个位置(这是->
所做的)。对不起,我会修正我的答案。@amalloy该死的Clojure;第三个答案,回答者又错了!:-)你们的二传手都还这个?如果不是,那么您将希望使用(doto…)这不是真的。画眉是一种类似于->
的功能->
和->
是宏,我通常听说它们被称为“线程化”宏,因为它们将第一个窗体“线程化”到其余窗体,从而生成一个缝合在一起的窗体。这是不准确的。2不会被发送到函数调用(+3)
。。。相反,宏将代码从say(>abc)
重新排列为(c(ba))
主要是玩文字游戏,但我接受批评。谢谢你的澄清。@nicolas自从我提交答案的那天起,我就一直想更新我的答案,因为它令人困惑,但网站不让我更新。我对答案做了一个早该更新的更新。嘿,我对你的解释有疑问,你写了(->expr f1 f2 f3);与(f3(f2(f1 expr)))相同,但(-2(+3)(-7))
不等于(-7(+32))
第一个的结果是-2
,但第二个是2
你能帮我解释一下我的误解吗?
(macroexpand `(-> 42 inc dec))