How to write readable Clojure Code?

I am new to Clojure. I can understand the code I write but it becomes too difficult to understand it later.It becomes difficult to match parentheses.

What are the generic conventions to follow regarding naming conventions andindentation in various situations?

For example I wrote a sample de-structuring example to understand but it looks completely unreadable the second time.

(defn f [{x :x y :y z :z [a b c] :coll}] (print x " " y  " " z " " a " " b " " c)) 

In case of de-structuring, is it better to do it directly at the parameter level or start a let form and then continue there?

2

Naming conventions

  • stay lowercase for functions
  • use - for hyphenation (what would be underscore or camel case in other languages).

    (defn add-one
    [i]
    (inc i))

  • Predicates (i.e. functions returning true or false) end with ?
    Examples: odd? even? nil? empty?

  • State changing procedures end in !. You remember set! right? or swap!

  • Choose short variable name lengths depending on their reach. That means if you have a really small auxiliary variable you can often just use a one-letter name. (map (fn [[k v]] (inc v)) {:test 4 :blub 5}) choose longer variable names as needed, especially if they are used for lots of code lines and you cannot immediately guess their purpose. (my opinion).

    I feel that a lot of clojure programmers tend to rather use generic and short names. But this is of course not really an objective observation. The point is that a lot of clojure functions are actually quite generic.

    • Use meaningful names.Procedures are doing something, therefor you can best describe them by using verbs. Clojure built-in functions should put you on the right track: drop, take, assoc, etc. Then there is a nice article describing ways to choose a meaningful name: http://ecmendenhall.github.io/blog/blog/2013/09/02/clean-clojure-meaningful-names/

Lambda functions

  • You can actually name lambda functions. This is convenient for debugging and profiling (my experience here is with ClojureScript).

    (fn square-em [[k v]] {k (* v v)})

  • Use inline lambda functions #() as convenient

Whitespace

  • There should not be parens-only lines. I.e. close the parentheses right away. Remember parens are there for editor and compiler, indentation is for you.

  • Function parameter lists go on a new line

   (defn cons
     [a b]
     (list a b))

This makes sense if you think about the doc strings. They are between the function name and parameters. The following doc string is probably not the wisest 😉

   (defn cons
     "Pairing up things"
     [a b]
     (list a b))
  • Paired data can be separated by a new line as long as you retain the pairing
  (defn f 
    [{x :x 
      y :y 
      z :z  
      [a b c] :coll}] 
    (print x " " y  " " z " " a " " b " " c)) 

(You can also enter , as you like but this feels unclojurish).

  • For indentation use a sufficiently good editor. Years ago this was emacs for lisp editing, vim is also great today. Typical clojure IDEs should also provide this functionality. Just do not use a random text editor.

    In vim in command mode you can use the = command to properly indent.

  • If command get too long (nested, etc.) you can insert a newline after the first argument. Now the following code is pretty senseless but it illustrates how you can group and indent expressions:

(+ (if-let [age (:personal-age coll)]
     (if (> age 18)
       age
       0))
   (count (range (- 3 b)
                 (reduce + 
                         (range b 10)))))

Good indentation means that you do not have to count brackets. The brackets are for the computer (to interpret the source code and to indent it). Indentation is for your easy understanding.

Higher order functions vs. for and doseq forms

Coming from a Scheme background I was rather proud to have understood map and lambda functions, etc. So quite often, I would write something like this


(map (fn [[k x]] (+ x (k data))) {:a 10 :b 20 :c 30})

This is quite hard to read. The for form is way nicer:

(for [[k x] {:a 10 :b 20 :c30}]
  (+ x (k data)))

`map has a lot of uses and is really nice if you are using named functions. I.e.

(map inc [12 30 10]

(map count [[10 20 23] [1 2 3 4 5] (range 5)])

Use Threading macros

Use the threading macros -> and ->> as well as doto when applicable.

The point is that threading macros make the source code appear more linear than function composition. The following piece of code is pretty unreadable without the threading macro:

   (f (g (h 3) 10) [10 3 2 3])

compare with

   (-> 
     (h 3)
     (g 10)
     (f [10 3 2 3]))

By using the threading macro, one can typically avoid introducing temporary variables that are only used once.

Other Things

  • Use docstrings
  • keep functions short
  • read other clojure code

5

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật