Code Monkey home page Code Monkey logo

clojure-style-guide's People

Contributors

arrdem avatar bbatsov avatar ccfontes avatar cloojure avatar cris avatar danielcompton avatar ericdlaspe avatar ghoseb avatar gonzih avatar heliosmaster avatar holyjak avatar leavenha avatar llasram avatar lread avatar lvh avatar marknsikora avatar nondv avatar r6eve avatar rafaelzlisboa avatar rbf avatar saolsen avatar seancorfield avatar shamsimam avatar ska2342 avatar skaplan avatar sumbach avatar totakke avatar uvtc avatar walterl avatar yakryder avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

clojure-style-guide's Issues

Mention the comment macro

Sometimes it useful to comment out multiple lines. That can be done with the comment macro:

(comment
  (some-code-1)
  (some-code-2)
  (some-code-3))

Maybe it's worth to mention that in style guide.

Parentheses instead of brackets in ns declaration.

Originally posted in this issue.

I believe that we should use parentheses instead of brackets inside of namespace declarations. The first word of the inner form is special, and thus it should be a list, keeping consistent with the rest of clojure. An example is below; notice where we use both :as and :refer in the same declaration.

    (ns examples.ns
      (:refer-clojure :exclude [next replace remove])
      (:require (clojure (string :as string
                                 :refer [capitalize])
                         (set :as set)
                         (zip :refer :all)
                         (xml :refer :all))
                (clojure.java (shell :as sh)))
      (:import java.util.Date
               java.text.SimpleDateFormat
               (java.util.concurrent Executors
                                     LinkedBlockingQueue)))

Notably, emacs will automatically indent this properly, which it will not do with a vector. One downside of this approach is that it does not work for namespaces without packages (rare). Another is that it is not compatible with clojurescript.

I have been using this approach for months and have found it agreeable.

Collection (Set) literal syntax should only be used with compile time constants

The Collections section should elaborate on when set literal syntax is not appropriate, i.e. when the values in the set are not compile time constants.

There's been recent discussion on this on the Clojure ML[1] and it's spawned a wiki page[2] The consensus is (AFAICT) that if there's a possibility of duplicate values the constructor functions are preferred over literal syntax. There's further discussion on whether duplicates are appropriate in literals, but I don't think that's worth adding here.

I propose adding the following

  • Only use set literal notation when set values are compile-time constants
; good
(hash-set (func1) (func2))

; bad, will throw exception if (func1) == (func2)  at runtime.
#{(func1) (func2)}

[1] https://groups.google.com/forum/?fromgroups=#!topic/clojure/AG667ACBd3I
[2] http://dev.clojure.org/display/design/Allow+duplicate+map+keys+and+set+elements

why indent multi line docstrings?

I disagree with "Indent each line of multi-line docstrings." This results in extra spaces inserted at arbitrary intervals in the resulting string, making docstring maintenance more of a pain - if I'd like to insert text I'll likely need to update a number of other lines lower down in the docstring. Even without this spacing I'd likely need to update line breaks, but updating the spacing feels like an unneeded additional hassle.

Certainly open to other thoughts, but I'm curious about the justification for this rule...

Use empty? to determine whether a seq is empty

empty? is simple, direct, and effective. The use of seq as a drop-in replacement for (complement empty?) is not style worth propagating, because it doesn't encourage straight-forward code readability.

Simple defn

If there is no docstring for a defn, should it be "good style" to keep the name and arg vector on one line? I'll open a pull request if there is a consensus on this.

;; good
(defn foo
  [x y]
  (...))

;; acceptable (no docstring)
(defn foo [x y]
  (...))

-> versus . when using records

I'd like to hear the reasons behind choosing a particular way of populating a record.

(defrecord Example [name] [value])

(Example. "hello" "world")
(->Example "hello" "world")

I think it makes more sense to use the . notation because it makes it evident that we're working with a Java class that defrecord generates. Using the ->RecordName approach makes me think twice: "Did the developer leave a typo here and intend this to mean thread RecordName, (i.e. did they intend to use the threading macro)?"

What are the community's thoughts?

third bullet point in "Annotations" section -- 2 spaces?

Regarding the item in the Annotations section beginning "If multiple lines are required to describe the problem", it's unclear where the 2 spaces are. Are they being rendered in the example code block?

Also, is this one necessary?

Also, what looks nice as well is:

(defn some-fun
  []
  ;; FIXME: This has crashed occasionally since v1.2.3. It may
  ;;        be related to the BarBazUtil upgrade. To reproduce,
  ;;        try fine-tuning the frobnicator.
  (baz))

No clear style for multimethods

Where to put the dispatch-val for a multimethod is not covered by the style guide. Personally I see a few solutions.

(defmulti example keyword)

(defmethod example
  :foo [c]
  :a-foo)

(defmethod example :bar
  [c]
  :a-bar)

(defmethod example
  :baz
  [c]
  :a-baz)

Personally I'm in favour of the bar example. But I will yield to the judgment of the clojure community.

Clarify meaning of "Annotations"

It's unclear at first what's meant by "Annotations". Maybe change the header to "Annotations in Comments", or else maybe modify the first list item from

  • Annotations should usually be ...

to

  • Annotations (comments beginning with "TODO", "FIXME", etc.) should usually be ...

heading, top-level, and trailing comments

Re. "The only comments in which omission of a space between the semicolon and the text is acceptable are margin comments."

Leaving out the space there looks bad, IMO. I don't think that should be in the style guide.

Also, where does the tradition of triple and quadruple semicolons come from? Is that from Elisp? The only Clojure project I know of that reads comments --- and does something with them --- is Marginalia. AFAIK, it treats full-line comments as markdown input, and uses the double-semicolon throughout. For example, see https://github.com/fogus/marginalia/blob/master/src/marginalia/core.clj .

If anything, I'd recommend that comments be written in such a way as to be correctly renderable by Marginalia (I haven't looked into how it handles triple and quad semicolons).

Fixing indentation of example code in docstring

Having a doc string with example code that spans over multiple lines and needs indentation is not properly formatted due to clojure removing any leading whitespace on each line:

(defn ex
  "foo
   (let [x '10]
     (+ x 10)"
  [])

Multiple solutions can be proposed:

A.

(defn ex
  "foo
    (let [x '10]
    ,,(+ x 10)"
  [])

B.

(defn ex
  "foo
    (let [x '10]
    __(+ x 10)"
  [])

C.

(defn ex
  "foo
    (let [x '10]
    ..(+ x 10)"
  [])

Or simply prefixing the lines:

D.

(defn ex
  "foo
   | (let [x '10]
   |   (+ x 10)"
  [])

E.

(defn ex
  "foo
   > (let [x '10]
   >   (+ x 10)"
  [])

Any thoughts what should be recommended? I personally like D (and also E).

Proposal: Sort arities from fewest to most

so

(fn ([x] ...) ([x y] ...) ([x y z & more] ...))

Since the common case of multiple arity functions is that you have several partial application arities, one "full" arity and then a varargs case which is a foldr over the varargs. This is also in keeping with the style clojure.core uses for such functions.

Prefer -> over ..

I was under the impression .. is out of favro ever since the introduction of the -> macro.

Changes for ebook versions

I've forked the repo and made changes to it that provide for a better experience in ebooks (as well as HTML and PDF versions). This did require some changes to the source document.

If you are interested in having the changes merged back into your project, I will create a PR.

Here's the fork, for your review:

Thanks for taking the time to create such a great resource for the community!

Quote about syntactic sugar

There is excellent quote by Alan Perlis:

Syntactic sugar causes semicolon cancer.

In fact, it is not only about semicolons. Would be good to see such update in section "Don't use commas between the elements of sequential collection literals."

Destructuring in function definition

Hello.

Is it recommended to destructure arguments in function definition or in let inside the function? The first approach affects readability though shortens the function. Any thoughts about this? E.g. compare

(defn distance-to-unit 
  [{:keys [scale units-per-pixel] :as viewer} dim value])

and

(defn distance-to-unit 
  [viewer dim value]
    (let [scale (:scale viewer)
          units-per-pixel (:units-per-pixel viewer)]))

Indentation of keywords in head position of vector

I know this isn't a widely accepted Clojure indentation rule yet, but consider the following code:

(defn foo []
  (html [:div {:class "bar"}
         [:span "first child"]
         [:span "second child"]]))

I think in 99.9% of cases having a keyword as the initial position of a vector indicates that the vector is representing a syntax expression for a DSL. In this case, it makes sense to indent the other items in the vector in the same manner as function arguments:

(defn foo []
  (html [:div {:class "bar"}
              [:span "first child"]
              [:span "second child"]]))

In any case I've ever come across this situation in my own code, this would be the more sensible way to do indentation. If, per chance, other Clojurists agree with my thinking, I think it would be an awesome addition to your style guide.

Multi-line doc strings

I'm never sure whether to do this:

(defn foo
  "hello there. this is
  a multi-line doc"
  (inc 1))

or this:

(defn foo
  "hello there. this is
a multi-line doc"
  (inc 1))

Thoughts?

Indenting metadata objects

Hello all,
we are discussing a formatting problem here and I thought I could give clojure-style-guide a spin.

Basically we are indenting metadata. A proposal in the issue above is as follows...

Before:

(deftest ^{:doc "Some doc
                 More doc."}
<test-name>
<body>)

After:

(deftest ^{:doc "Some doc
                 More doc."}
  <test-name>
  <body>)

What does the community think about it?

Example is not correct Clojure

In the metadata section, an example shows:

(def a ^:private 5)

That's not possible in any version of Clojure I know as Java.lang.Long doesn't support IMeta.

Perhaps the example could be

(def a ^:private {})

Add rationale

In a lot of places here, there's a rule (say: "avoid ref-set and use alter instead") but no explanation is given as to why the former needs to be avoided. This happens in several places. I'd really enjoy knowing why it's that way (a link would totally suffice)

thanks!

:use is not encouraged anymore

Not like I wholeheartedly agree with that (the day we have even better tooling we'll be able to use :use liberally), but since Clojure 1.4 they are considered bad practice.

Surely it's worth reflecting this to some extent?

Pre-conditions should not be used when IllegalArgumentException is appropriate

As Clojure is currently implemented, a failing pre- or post-condition throws an AssertionError, as opposed to an Exception. Errors are subclasses of Throwable but not of Exception: http://docs.oracle.com/javase/7/docs/api/java/lang/Error.html. Per the javadoc on Error: "An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions."

Things like ensuring an input is a positive number, ensuring certain keys are in a map, etc. are things that should typically be Exceptions.

http://programmers.stackexchange.com/questions/137158/is-it-better-to-use-assert-or-illegalargumentexception-for-required-method-param

Confusing indentation rules

There are 2 rules which confuse me:

  • Use two spaces per indentation level. No hard tabs.

    ;; good
    (when something
      (something-else))
    
    ;; bad - four spaces
    (when something
        (something-else))
  • Vertically align function arguments.

    ;; good
    (filter even?
            (range 1 10))
    
    ;; bad
    (filter even?
      (range 1 10))

The question is when should 2-space indentation be used? Is there a fixed set of macros/special forms that should be 2-space indendent like def, defn, if, when, let, etc? Can we clarify the set or was it considered and then rejected?

Typo in the rule for sugared Java interop

The last line of the example in the rule for sugared Java interop might be typo.

  • Use the sugared Java interop forms.

    ...
    ;;; instance field access
    ;; good
    (.someField some-object)
    
    ;; bad
    (. some-object some-field) ; <-typo

Correct code is (. some-object someField).

Proposal for how to handle sequences of pairs where left/right don't fit on one line.

One of the differences in Clojure from other Lisps that I have used is that frequently there are pairs of s-expressions without enclosing parentheses. These show up in binding vectors in let,when,if-let and their relatives. These pairs also show up in assoc, cond, condp, and case.

I like this syntactic clarity, but when writing code with other than single character local names in let, and with expressions for assoc, sometimes the pairs don't fit on the same line. In this case, the default approach is to simply place them all in line on the left. I find this difficult to read.

I have taken to indenting what would be the right-hand side of the pair (if it were on the same line) by 2 spaces so that the left-right relationship remains clear even if the two "sides" are on different lines.

; default approach
(let [local-value1 (expr1)
      another-value (expr2)
      third-value 
      (a (very (long (expression (that (doesnt (fit on) one line))))))
      result-of-the-long-expression
      (another (expression (that (is too long) for one) line))]
  (result-of-the-long-expression))

; a possibly better alternative
(let [local-value1 (expr1)
      another-value (expr2)
      third-value 
        (a (very (long (expression (that (doesnt (fit on) one line))))))
      result-of-the-long-expression
        (another (expression (that (is too long) for one) line))]
  (result-of-the-long-expression))

I have not seen anyone else do this, so I certainly can't say that this is idiomatic Clojure. However, I wanted to bring it up for discussion and consideration.

Of course, one approach is to not let this happen. But at least in my code, I sometimes have rather complex expressions on the right hand side of let binding vectors, as well as on both sides of assoc pair lists. To say nothing of cond and friends.

nil punning confusing?

This is probably getting dangerously close to personal preference territory, but

;; bad
(defn print-seq [s]
  (when-not (empty? s)
    (prn (first s))
    (recur (rest s))))

reads a lot better to me than

;; good
(defn print-seq [s]
  (when (seq s)
    (prn (first s))
    (recur (rest s))))

even after having used Clojure for 3 years, including lots of time writing it for my day job. Is there something we could link to explaining why nil punning is desirable/better here?

ambiguous terminology for function literals

in https://github.com/bbatsov/clojure-style-guide#no-multiple-forms-fn-literals, it says:

Don't use function literals if the function body will consist of more than one form.

   ;; good
   (fn [x]
     (println x)
     (* x 2))

  ;; bad (you need an explicit do form)
  #(do (println %)
       (* % 2))

I don't know what the official Clojure terms are for these, but I find the naming very confusing because both examples are using function literals (at least from a certain point of view -- arguably, the (fn ...) form is a list). Maybe the #(...) syntactic form should be referred to as a shorthand function literal?

Consider modifying the 'commas' section.

Hey Bozhidar,

;; comas enhance the map literal's readability
{:name "Bruce Wayne", :alter-ego "Batman"}

My personal experience is that commas don't enhance readability of the code, but do increase the number of keystrokes required to alter that code.

Off-topic, but have to taken a look at Taylor Campbell's scheme style guide? Might help to fill in any gaps.

http://mumble.net/~campbell/scheme/style.txt

Just my 2c, thanks for your work here.

Indenting cond

The indentation for cond in the guide uses two spaces, but clojure-mode enforces one space. Given that clojure-mode is actively used, should we update the guide?

Suggestion for documenting arguments to a partially applied function?

I'd like to know whether there's an idiomatic way to document the arguments to a partially applied function (or any function without an explicit args vector):

(def foo (partial bar baz))
; or
(def foo (comp bar qux))

I'd probably do something like:

(def foo "[arg-1 arg-2] -> result" (partial bar baz))

Does a common means of documenting this exist? And if it does, should it be in this guide?

defn- vs. defn ^:private

Looking here it is suggested that

;; good
(defn- private-fun [] ...)

(defn ^:private private-fun [] ...) ; overly verbose

However reading up on this Google group discussion it seems that using defn- is a bit contradictory since there are other def that do not have a complimentary def- option. Quoting Vincent

It's better to use ^:private metadata on the symbol naming the var, since there is also defmacro, defmulti, etc, which not have hyphened versions too.

Should this continue to remain in the styleguide?

(I can submit a PR to make the change, however I felt that perhaps having a discussion prior to that would be appropriate)

"Oneliners" with and without documentation

I would like to clarify (and maybe enhance) formatting of simple functions.

According to current standard, following example is bad

(defn foobar 
  [x] (-> x foo bar baz))

correct indentation in two lines is

(defn foobar [x] 
  (-> x foo bar baz))

or in three lines with newline:

(defn foobar 
  [x] 
  (-> x foo bar baz))

I see there two inconsistencies, because a) multiarity functions allow similar indentation, so simply killing [x y] arity should lead to correct formatting.

(defn foobar 
  ([x] (-> x foo bar baz))
  ([x y] (-> x foo (bar y) baz)))

and b) neither two liner or three-liner play nice with docstring. There I would expect to see short version in three lines. Again, removing docstring should lead to correct formatting.

(defn foobar
   "Does foo, bar and baz to x"
    [x] (-> x foo bar baz))

I apologize in advance for nitpicking and starting worst code formatting flamewar ever.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.