3 ms·
I didn't know that Clojure puts function comments between the function name and the parameters. I personally find that a bit awkward - wouldn't it make more sen
by kleiba 13y ago
I didn't know that Clojure puts function comments between the function name and the parameters. I personally find that a bit awkward - wouldn't it make more sense to have it after the parameters, to allow to simply glance at the function definition and see its signature, especially when comments extend over multiple lines?
- Tuna-Fish 13y agoFunctions can have several different parameter lists and separate implementations for each one. In practice, this is done by grouping the parameter list of each version with it's body. Where would you put the docstring in: (defn foo ([x] "bar") ([x y] "baz")) ?
- kleiba 13y agoI'd probably put it after the parameter lists: (defn foo ([x] *docstring* "bar") ([x y] *docstring* "baz")) because you want to be able to document the different implementations differently. The semantics would be: If the function body starts with a string literal, the latter serves as the documentation. If the body consists of any other code following the string literal, it will be ignored for run-time processing; if it's the only thing in the body, it also serves as the return value.
- Tuna-Fish 13y ago> because you want to be able to document the different implementations differently. I disagree with this. Since the normal functions cannot dispatch on type⁺, only arity, the different implementations are typically very related and should share same documentation. Your proposal would lead to massive duplication, and reduce the likelihood of people actually documenting the functions. ⁺ There are two separate mechanisms for providing richer function dispatch, both allow more granular documentation.
- kleiba 13y agoYeah, I guess you've got a point there. However, if this only applies to different arities, please also compare to the following style: (defun function (a b &optional c d e) "Documentation string" "return value")) I still think that the function signature is more readable when the doc string comes after the parameters, but perhaps it's just a matter of taste. The above is obviously not Clojure. But as I commented originally, I just wasn't aware that this is the way Clojure does it.
- Tuna-Fish 13y agoThat could be done as: (defn function "doc" [a b & rest] "body") However, matching by arity at the front really helps make simple functions clean. I really like the multiple body approach, as in my code there's typically one "standard" case, and the rest are special cases that just call the standard one with new params. Having to deal with a rest arg with potentially multiple possible lengths just doesn't look as clear in practice. It's all tradeoffs. I can see why you'd like the arglist first -- I have some Haskell background, and I do miss it's types in Clojure, just for the documentation they provide.
- mcav 13y agoIt's ambiguous the other way: (defn some-string [] "is this a docstring or a return value?")
- DigitalJack 13y agoClojure works with it in either case, and it is not ambiguous due to the arity of defn.
- weavejester 13y agoI think you're misunderstanding, because (a) no it doesn't, and (b) no it isn't :) Clojure docstrings need to precede the argument list. e.g. this is correct: (defn foo "Some docstring" [] "Some return value")) But this is not: (defn foo [] "Some docstring" "Some return value")) It will still compile, but the first string will be treated as an expression, and therefore ignored as it has no side effects. The reason docstrings in Clojure come before the arguments, is that because if they came after, their effect would be ambiguous, regardless of arity. e.g. (defn foo [] "foo") Is the string supposed to be the return value of the function, or its docstring?
- kleiba 13y agoOther Lisps do it that way without a problem: - If the function body starts with a string literal, it is always the doc-string - If that string is the only thing in the function body, it is also the return value.
- weavejester 13y agoSure, you can conceive of more complex rules to solve the problem, but that's complicating the syntax for little benefit. You can no longer say "The docstring comes before the arguments". You instead have to say something like "The docstring is the first evaluated expression in the function if the expression is a string, unless the function has multiple arities, in which case the docstring precedes the function's arguments and any isolated string expressions in the bodies will be ignored."