What does -> do in clojure?

前端 未结 6 1257
既然无缘
既然无缘 2021-02-01 04:02

I have seen the clojure symbol -> used in many places, but I am unsure as to what this symbol is called and does, or even whether it is part of standard clojure. Could someone e

相关标签:
6条回答
  • 2021-02-01 04:44

    It's a way to write code left to right, instead of inside out, e.g.

    (reduce (map (map xs bar) foo) baz)
    

    becomes

    (-> xs (map bar) (map foo) (reduce baz))
    

    You might want to read the source, it's here.

    EDIT: Fixed my confusion of -> with ->>, thanks to amalloy. Sadly my example is now quite unlikely to appear in practice.

    0 讨论(0)
  • 2021-02-01 04:45

    You can see for yourself:

    (macroexpand `(-> 42 inc dec))
    
    0 讨论(0)
  • 2021-02-01 04:47

    I did not fully get what -> (thrush or thread) did until I visualized it like this:

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

    Here are some examples:

    (-> 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
    
    0 讨论(0)
  • 2021-02-01 04:53

    -> uses the result of a function call and send it, in sequence, to the next function call.

    So, the easier example would be:

     (-> 2 (+ 3))
    

    Returns 5, because it sends 2, to the next function call (+ 3)

    Building up on this,

    (-> 2 
      (+ 3) 
      (- 7))
    

    Returns -2. We keep the result of the first call, (+ 3) and send it to the second call (- 7).

    As noted by @bending, the accepted answer would have been better showing the doto macro.

    (doto person
      (.setFName "Joe")
      (.setLName "Bob")
      (.setHeight [6 2]))
    
    0 讨论(0)
  • 2021-02-01 05:02

    It's called the thrush operator. It's best explained here.

    0 讨论(0)
  • 2021-02-01 05:06

    '->' is a macro. The best way to describe it, I think, is in the example of the "dot special form" for which it serves the purpose of making the code more terse and legible as is indicated on the clojure.org website's explanation of the The Dot special form

    (.. System (getProperties) (get "os.name"))
    

    expands to:

    (. (. System (getProperties)) (get "os.name"))
    

    but is easier to write, read, and understand. See also the -> macro which can be used similarly:

    (-> (System/getProperties) (.get "os.name"))
    

    There is also 'doto'. Let's say you have a single object on which you'd like to call several consecutive setters. You could use 'doto'.

    (doto person
      (.setFName "Joe")
      (.setLName "Bob")
      (.setHeight [6 2]))
    

    In the above example the setters don't return anything, making 'doto' the appropriate choice. The -> would not work in place of 'doto' unless the setters returned 'this'.

    So, those are some techniques related to the -> macro. I hope that helps explain not only what they do, but also why they exist.

    0 讨论(0)
提交回复
热议问题