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做什么?_Clojure - Fatal编程技术网

什么是->;你在clojure做什么?

什么是->;你在clojure做什么?,clojure,Clojure,我见过clojure符号->在许多地方使用,但我不确定该符号的名称和作用,甚至不确定它是否是标准clojure的一部分。有人能给我解释一下吗?这叫画眉操作符。这是最好的解释。这是一种从左到右编写代码的方法,而不是从内到外,例如 (reduce (map (map xs bar) foo) baz) 变成 (-> xs (map bar) (map foo) (reduce baz)) 你可能想读源代码,它是 编辑:修复了我对->和->的混淆,多亏了amalloy。遗憾的是,我的示例现在

我见过clojure符号->在许多地方使用,但我不确定该符号的名称和作用,甚至不确定它是否是标准clojure的一部分。有人能给我解释一下吗?

这叫画眉操作符。这是最好的解释。

这是一种从左到右编写代码的方法,而不是从内到外,例如

(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))