5 ms·
Clojure isn't particularly well suited to avoiding problems like this. I've written a lot of Clojure for work and for open source. We need pure, typed FP langs
by coolsunglasses 13y ago
Clojure isn't particularly well suited to avoiding problems like this. I've written a lot of Clojure for work and for open source.
We need pure, typed FP langs like Haskell/Agda/Idris.
To boot, I'm having a much more enjoyable and relaxing time in a Haskell REPL than I was in my Clojure REPL.
Somebody I follow on Twitter just said something apropos:
"girl are you Clojure because when I'm with you I have a misplaced sense of [optimism] about my abilities until I enter the real world"
- loumf 13y agoI don't think clojure (or lisp) was designed to avoid line-duplication errors. It's mostly an accident of it being not very line oriented. I just randomly picked a function from core to illustrate this, but a lot of clojure code looks similar (defn filter "Returns a lazy sequence of the items in coll for which (pred item) returns true. pred must be free of side-effects." {:added "1.0" :static true} ([pred coll] (lazy-seq (when-let [s (seq coll)] (if (chunked-seq? s) (let [c (chunk-first s) size (count c) b (chunk-buffer size)] (dotimes [i size] (when (pred (.nth c i)) (chunk-append b (.nth c i)))) (chunk-cons (chunk b) (filter pred (chunk-rest s)))) (let [f (first s) r (rest s)] (if (pred f) (cons f (filter pred r)) (filter pred r)))))))) There are very few lines of this function that can be duplicated without causing a syntax error because parens will be unbalanced. I see two: In a let with more than two bindings, you could repeat the middle ones. In clojure, this is very likely to be idempotent. In this code, it's the size (count c) In any function call with more than two arguments, if the middle ones are put on their own line, they could be repeated, like this in the final 'if' (cons f (filter pred r)) In many cases, you will fail the arity check (for example in this case). If not, the function should fail spectacularly if you run it. So, I think it's accidentally less likely to have problems with bad merges and accidental edits (not designed to have that property)
- deleted 13y ago[deleted]
- yohanatan 13y agoYour analysis only holds if closing parentheses are all gathered on the same line as final expressions (which may not be true for some styles).
- loumf 13y agoI'm not thinking this through completely, but it seems resilient to a lot of styles. Function calls (which is a lot of what clojure is) are an open parens to start and very likely not to have that close on the same line (because you are building a tree of subexpressions). Wherever you put the close (bunched or one per line), if you don't put it on the line with the original open, it will be unbalanced in both spots (meaning the first line and the last line can't be duplicated without causing a syntax error).
- yohanatan 13y agoTrue. But consider the form: (if (someExpr) (doTrueStuff) ) Then a duplication of the `doTrueStuff` line would lead to true stuff being done regardless of the truthiness of someExpr (as the third [optional] argument to `if` is the else branch). This form is not entirely unheard of either. The overtone library for example assigns labels to its event handlers like such: (defn eventHandler ( ... stuff ) :: event_handler_label)
- Jtsummers 13y agoThis is actually why I really like `cond` in Common Lisp (and other lisps and languages). You have to make explicit what should happen if your desired expression is true, and the only way to have an `else` clause is `(t ...)` so you have to intentionally create that last wildcard spot.
- chc 13y agoIt is considered unidiomatic in every Lisp I am aware of to orphan parens. To some degree this is a stylistic concern, but it's a much more open-and-shut case than, say, C brace style.
- mercurial 13y agoEven in Haskell you can fairly easily get non-reachable code: if a == a then ... else -- unreachable Combine this with the unfortunate habit (which I'm also guilty of) of allowing variables to be called a' and you'll an easy-to-miss bug.
- WolfeReader 13y agoGiven that types may define their own instances of Eq, the else clause might be reachable.