4 ms·
I don't know enough Clojure to really understand this argument. I am a bit confused by the example. It appears that the only difference between "semantic" and "
by ulrikrasmussen 6y ago
I don't know enough Clojure to really understand this argument. I am a bit confused by the example. It appears that the only difference between "semantic" and "fixed" indentation is that the former allows "hanging indentation" of the arguments, i.e. aligning everything to match the indentation of the first argument when that was not preceded by a newline but placed immediately after the identifier of the function being called. I don't understand how that has anything to do with macros as it is claimed in the article, but that is probably due to my lack of Clojure knowledge.
I think there is an important - but often ignored - argument against "hanging indentation", and that is that it makes the indentation of a possibly large number of lines depend on the length of the identifier or expression that the arguments are applied to. This can result in larger than necessary diffs when refactoring, leading to unnecessary conflicts during integration. Furthermore, unless you have tooling that is aware of this indentation style, code modifications may require a lot of manual and tedious re-indentation.
- hibbelig 6y agoThe cases where hanging indentation is used are plain function calls. The places where the other kind of indentation is used are similar to control structures in other languages. In C like languages you can tell by the curly braces that it’s a control structure (if, while,...). In Clojure they all use parentheses. In Clojure you can define your own control structures, and the way to do that is using macros. That’s why the article talks about macros. Does that help?
- ulrikrasmussen 6y agoYes, I think I understand that. The idea is to make a visual distinction between a function call and a macro invocation, as the latter is used as a mechanism to provide control structures that are usually built-in in Algol-like languages. I'm just not sure I actually understand how that distinction is supposed to be implemented by the "semantic indentation" style. The example in the article only shows how there is a difference between the styles for _function calls_ (calls to `filter`). But I suspect the example is just a bad one for illustrating the authors point. In general though, I think hanging indentation is a bad idea for the reasons I stated above :).
- hibbelig 6y ago> I'm just not sure I actually understand how that distinction is supposed to be implemented by the "semantic indentation" style. Given an expression such as (foo bar baz), semantic indentation examines foo to determine whether it is a macro or a function, and produces two different indentations depending on the result. Fixed indentation always produces the same result, regardless of whether foo is a macro or not. The "semantic" in the name refers to the deeper analysis required: If you see a "defmacro" somewhere then you have to remember that it is a macro. (I think actually, it's a bit more complicated. Macros can have multiple arguments, and one is often special. Look at the control structure "when": it receives a condition and multiple "statements", and when the condition is true all statements are executed, in order. And semantic indentation knows this. So you get this: (when CONDITION STMT-1 STMT-2) But when you put the condition on an extra line, you get this: (when CONDITION STMT-1 STMT-2) Fixed indentation has no idea and produces the following hard-to-read thing instead: (when CONDITION STMT-1 STMT-2)
- ulrikrasmussen 6y agoThank you, this makes sense.
- fiddlerwoaroof 6y agoI almost always edit Clojure in emacs with aggressive-indent-mode enabled. Effectively, what this means is that the buffer is always formatted: every keypress triggers reindentation of the entire buffer and emacs “knows” about these semantic indentation rules. With this setup, the rules are pretty trivial to enforce and other environments, such as Calva or Cursive, can be configured to approximate this pretty closely. I dislike this style in other languages, but in lisps, the two-dimensional layout it creates is very useful for quickly scanning code and understanding its structure.
- anentropic 6y agoI had the same question... The first example code block is followed by the text: > I hope it’s obvious that the main difference is that “semantic indentation” differentiates between macros with body forms and regular function/macro invocations. But in the example code block the two "macros" examples were formatted identically in 'fixed' and 'semantic' styles. The only one that was different is "function call spanning two lines". So the stated point is far from obvious.
- WalterGR 6y agoThis can result in larger than necessary diffs when refactoring, leading to unnecessary conflicts during integration. Semantic versions of those could be interesting.