Transplant style guide from hylang/hy-style-guide

This commit is contained in:
Kevin Yap 2015-01-02 19:56:07 -08:00
parent 34fb8a778c
commit a160c74a42
2 changed files with 242 additions and 0 deletions

View File

@ -32,6 +32,7 @@ Contents:
quickstart quickstart
tutorial tutorial
style-guide
language/index language/index
contrib/index contrib/index
hacking hacking

241
docs/style-guide.rst Normal file
View File

@ -0,0 +1,241 @@
==============
Hy Style Guide
==============
“You know, Minister, I disagree with Dumbledore on many counts…but
you cannot deny hes got style…”
— Phineas Nigellus Black, Harry Potter & the Order of the Phoenix
The Hy style guide intends to be a set of ground rules for the Hyve
(yes, the Hy community prides itself in appending Hy to everything)
to write idiomatic Hy code. Hy derives a lot from Clojure & Common
Lisp, while always maintaining Python interopability.
Prelude
-------
The Tao of Hy
~~~~~~~~~~~~~
::
Ummon asked the head monk, "What sutra are you lecturing on?"
"The Nirvana Sutra."
"The Nirvana Sutra has the Four Virtues, hasn't it?"
"It has."
Ummon asked, picking up a cup, "How many virtues has this?"
"None at all," said the monk.
"But ancient people said it had, didn't they?" said Ummon.
"What do you think of what they said?"
Ummon struck the cup and asked, "You understand?"
"No," said the monk.
"Then," said Ummon, "You'd better go on with your lectures on the sutra."
— the (koan) macro
The following illustrates a brief list of design decisions that went
into the making of Hy.
+ Look like a lisp, DTRT with it (e.g. dashes turn to underscores,
earmuffs turn to all-caps.)
+ We're still Python. Most of the internals translate 1:1 to Python internals.
+ Use unicode everywhere.
+ Fix the bad decisions in Python 2 when we can (see true_division)
+ When in doubt, defer to Python.
+ If you're still unsure, defer to Clojure
+ If you're even more unsure, defer to Common Lisp
+ Keep in mind we're not Clojure. We're not Common Lisp. We're
Homoiconic Python, with extra bits that make sense.
Layout & Indentation
--------------------
+ Avoid trailing spaces. They suck!
+ Indentation shall be 2 spaces (no hard tabs), except when matching
the indentation of the previous line.
.. code-block:: clj
;; good (and preferred):
(defn fib [n]
(if (<= n 2)
n
(+ (fib (- n 1)) (fib (- n 2)))))
;; still OK:
(defn fib [n]
(if (<= n 2) n (+ (fib (- n 1)) (fib (- n 2)))))
;; still OK:
(defn fib [n]
(if (<= n 2)
n
(+ (fib (- n 1)) (fib (- n 2)))))
;; Stupid as hell
(defn fib [n]
(if (<= n 2)
n ;; Yes, I love randomly hitting the space key
(+ (fib (- n 1)) (fib (- n 2)))))
+ Parens must *never* be left alone, sad and lonesome on their own
line.
.. code-block:: clj
;; good (and preferred):
(defn fib [n]
(if (<= n 2)
n
(+ (fib (- n 1)) (fib (- n 2)))))
;; Stupid as hell
(defn fib [n]
(if (<= n 2)
n
(+ (fib (- n 1)) (fib (- n 2)))
)
) ; GAH, BURN IT WITH FIRE
+ **`let` blocks**
Align vertically the `let` blocks
.. code-block:: clj
(let [[foo (bar)]
[qux (baz)]]
(foo qux))
+ **Inline comments**
Inline comments shall be two spaces from the end of the code, they
must always have a space between the comment character and the start
of the comment. Also try not commenting the obvious
.. code-block:: clj
;; Good
(setv ind (dec x)) ; indexing starts from 0
;; Style compliant but just states the obvious
(setv ind (dec x)) ; sets index to x-1
;; Bad
(setv ind (dec x));typing words for fun
Coding Style
------------
+ As a convention, try not to use `def` for other than global
variables, use `setv` inside functions,loops etc.
.. code-block:: clj
;; good (and preferred)
(def *limit* 400000)
(defn fibs [a b]
(while true
(yield a)
(setv (, a b) (, b (+ a b)))))
;; bad & not preferred
(defn fibs [a b]
(while true
(yield a)
(def (, a b) (, b (+ a b)))))
+ Do not use the s-expression syntax where vector syntax is intended.
For instance, the fact that:
.. code-block:: clj
;; bad (and evil)
(defn foo (x) (print x))
(foo 1)
works is just because the compiler isn't overly strict. In reality,
the correct syntax in places such as this is:
.. code-block:: clj
;; good (and preferred):
(defn foo [x] (print x))
(foo 1)
+ Threading Macro
Use the threading macro or the threading tail macros when
encountering deeply nested s-expressions
.. code-block:: clj
;; preferred
(def *names*
(with [f (open "names.txt")]
(-> (.read f) (.strip) (.replace "\"" "") (.split ",") (sorted))))
;; not so good
(def *names*
(with [f (open "names.txt")]
(sorted (.spilt "," (.replace "\"" "" (.strip (.read f)))))))
However be judicious when using them, do use them when clarity and
readability improves. Do not construct convoluted hard to understand
expressions
.. code-block:: clj
;; This is probably not a good idea
(defn square? [x]
(->> 2 (pow (int (sqrt x))) (= x)))
+ Dot Notation
The clojure style dot notation is preferred over the direct call of
the object's method, though both will continue to be supported
.. code-block:: clj
;; good:
(with [fd (open "/etc/passwd")]
(print (.readlines fd)))
;; not so good:
(with [fd (open "/etc/passwd")]
(print (fd.readlines)))
Conclusion
----------
“Fashions fade, style is eternal”
—Yves Saint Laurent
This guide is just a set of community guidelines, obviously community
guidelines do not make sense without an active
community. Contributions are welcome. Join us at #hy in freenode, blog
about it, tweet about it, and importantly have fun with Hy
Thanks
------
+ This guide is heavily inspired from `@paultag`_ 's blog post `Hy
Survival Guide`_
+ The `Clojure Style Guide`_
.. _`Hy Survival Guide`: http://notes.pault.ag/hy-survival-guide/
.. _`Clojure Style Guide`: https://github.com/bbatsov/clojure-style-guide
.. _`@paultag`: https://github.com/paultag