How does one know when to newline in Clojure/Lisp in general?
Here is a bit of example code:
(deftype Deck52 [suits] :as this
DeckOfCards
(check-empty []
(Deck52. (apply hash-map
(apply concat (remove (-> nil?)
(for [[key val] suits]
(if (empty? val) nil [key val])))))))
(remove-card [suit card]
(assoc suits suit (remove #(= card %) (suit suits))))
(get-card [suit]
(let [suitd (suit suits)]
[(first suitd) (check-empty (Deck52. (assoc suits suit (rest suitd))))]))
(random-card []
(let [suitn (+ 1 (rand-int 4))]
(cond (= suitn 1) (get-card this :hearts)
(= suitn 2) (get-card this :diamonds)
开发者_如何学Python (= suitn 3) (get-card this :clubs)
(= suitn 4) (get-card this :spades)))))
I also posted this code in a Gist here if it's easier to read: http://gist.github.com/307425 (not going anywhere).
The primary example here is check-empty
. I had great difficulty knowing where I should and shouldn't hit return, and I still don't know if I did it right. It threatens to walk right off the right side of the screen, but that's the way clojure-mode indents, and I assume that it's supposed to be like that.
So, the question is, when is it time to place a newline in Clojure/Lisp code? Am I 'doin' it rite'?
NOTE: I can't promise that the code I posted works. I've been doing some experimentation, and some things might be plain ol' sucky, if not broken.
The way you broke the lines is quite normal. I would do some slight changes though.
- Put the argument vectors on the next line.
- Use different forms: the little
->
and->>
helpers, condp, when, ... - If necessary, break the line immediately after the function name.
Here how I would go about this. (Disclaimer: My style. Yours might be different. YMMV!)
(deftype Deck52 [suits] :as this
DeckOfCards
(check-empty
[]
(->> (for [[key val] suits]
(when-not (empty? val)
[key val]))
(remove nil?)
(apply concat)
(apply hash-map)
Deck52.))
(remove-card
[suit card]
(assoc suits suit (remove #(= card %) (suit suits))))
(get-card
[suit]
(let [suitd (suit suits)]
[(first suitd)
(->> (rest suitd)
(assoc suits suit)
Deck52.
check-empty)]))
(random-card
[]
(let [suitn (+ 1 (rand-int 4))]
(condp = suitn
1 (get-card this :hearts)
2 (get-card this :diamonds)
3 (get-card this :clubs)
4 (get-card this :spades)))))
Although the following is not part of your question, I cannot resist:
(deftype Deck52 [suits] :as this
DeckOfCards
(check-empty
[]
(->> suits (remove (comp nil? seq val)) (into {}) Deck52.))
(remove-card
[suit card]
(update-in suits [suit] #(remove %2 %1) #(= card %)))
(get-card
[suit]
(let [suitd (get suits suit)]
[(first suitd)
(->> (rest suitd) (assoc suits suit) Deck52. check-empty)]))
(random-card
[]
(case (rand-int 4)
0 (get-card this :hearts)
1 (get-card this :diamonds)
2 (get-card this :clubs)
3 (get-card this :spades))))
clojure-mode for Emacs doesn't necessarily get all the indentations right. I say try to keep your lines under 80 characters and be consistent.
when things are trying to escape off the right hand side I tend to his enter after the first argument to each call. this only indents by a fixed amount per line.
(check-empty []
(Deck52.
(apply
hash-map
(apply
concat
(remove
(->
nil?)
(for [[key val] suits]
(if (empty? val) nil [key val])))))))
精彩评论