2015-01-03 04:56:07 +01:00
|
|
|
|
==============
|
|
|
|
|
Hy Style Guide
|
|
|
|
|
==============
|
|
|
|
|
|
|
|
|
|
“You know, Minister, I disagree with Dumbledore on many counts…but
|
|
|
|
|
you cannot deny he’s got style…”
|
2015-01-03 05:25:07 +01:00
|
|
|
|
— Phineas Nigellus Black, *Harry Potter and the Order of the Phoenix*
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
|
|
|
|
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
|
2015-12-08 14:43:47 +01:00
|
|
|
|
Lisp, while always maintaining Python interoperability.
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
2015-01-03 04:58:46 +01:00
|
|
|
|
|
2015-01-03 04:56:07 +01:00
|
|
|
|
Prelude
|
2015-01-03 04:58:46 +01:00
|
|
|
|
=======
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
|
|
|
|
The Tao of Hy
|
2015-01-03 04:58:46 +01:00
|
|
|
|
-------------
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
2015-01-03 05:25:07 +01:00
|
|
|
|
.. code-block:: none
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
2019-01-24 17:57:10 +01:00
|
|
|
|
+ Look like a Lisp; DTRT with it (e.g. dashes turn to underscores).
|
2015-01-03 04:56:07 +01:00
|
|
|
|
+ We're still Python. Most of the internals translate 1:1 to Python internals.
|
2015-01-03 05:25:07 +01:00
|
|
|
|
+ Use Unicode everywhere.
|
|
|
|
|
+ Fix the bad decisions in Python 2 when we can (see ``true_division``).
|
2015-01-03 04:56:07 +01:00
|
|
|
|
+ When in doubt, defer to Python.
|
2015-01-03 05:25:07 +01:00
|
|
|
|
+ If you're still unsure, defer to Clojure.
|
|
|
|
|
+ If you're even more unsure, defer to Common Lisp.
|
2015-01-03 04:56:07 +01:00
|
|
|
|
+ Keep in mind we're not Clojure. We're not Common Lisp. We're
|
|
|
|
|
Homoiconic Python, with extra bits that make sense.
|
|
|
|
|
|
2015-01-03 04:58:46 +01:00
|
|
|
|
|
2015-01-03 04:56:07 +01:00
|
|
|
|
Layout & Indentation
|
2015-01-03 04:58:46 +01:00
|
|
|
|
====================
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
|
|
|
|
+ Avoid trailing spaces. They suck!
|
|
|
|
|
|
|
|
|
|
+ Indentation shall be 2 spaces (no hard tabs), except when matching
|
|
|
|
|
the indentation of the previous line.
|
|
|
|
|
|
2015-01-03 06:05:02 +01:00
|
|
|
|
.. code-block:: clj
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
2015-01-03 06:05:02 +01:00
|
|
|
|
;; Good (and preferred)
|
|
|
|
|
(defn fib [n]
|
|
|
|
|
(if (<= n 2)
|
2015-09-22 19:39:08 +02:00
|
|
|
|
n
|
|
|
|
|
(+ (fib (- n 1)) (fib (- n 2)))))
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
2015-01-03 06:05:02 +01:00
|
|
|
|
;; Still okay
|
|
|
|
|
(defn fib [n]
|
|
|
|
|
(if (<= n 2) n (+ (fib (- n 1)) (fib (- n 2)))))
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
2015-01-03 06:05:02 +01:00
|
|
|
|
;; Still okay
|
|
|
|
|
(defn fib [n]
|
2015-01-03 05:25:07 +01:00
|
|
|
|
(if (<= n 2)
|
2015-01-03 06:05:02 +01:00
|
|
|
|
n
|
2015-01-03 05:25:07 +01:00
|
|
|
|
(+ (fib (- n 1)) (fib (- n 2)))))
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
2015-01-03 06:05:02 +01:00
|
|
|
|
;; Hysterically ridiculous
|
|
|
|
|
(defn fib [n]
|
|
|
|
|
(if (<= n 2)
|
|
|
|
|
n ;; yes, I love randomly hitting the space key
|
|
|
|
|
(+ (fib (- n 1)) (fib (- n 2)))))
|
|
|
|
|
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
2015-01-03 05:25:07 +01:00
|
|
|
|
+ Parentheses must *never* be left alone, sad and lonesome on their own
|
2015-01-03 04:56:07 +01:00
|
|
|
|
line.
|
|
|
|
|
|
2015-01-03 06:05:02 +01:00
|
|
|
|
.. code-block:: clj
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
2015-01-03 06:05:02 +01:00
|
|
|
|
;; Good (and preferred)
|
|
|
|
|
(defn fib [n]
|
|
|
|
|
(if (<= n 2)
|
2015-09-22 19:39:08 +02:00
|
|
|
|
n
|
|
|
|
|
(+ (fib (- n 1)) (fib (- n 2)))))
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
2015-01-03 06:05:02 +01:00
|
|
|
|
;; Hysterically ridiculous
|
|
|
|
|
(defn fib [n]
|
2015-01-03 04:56:07 +01:00
|
|
|
|
(if (<= n 2)
|
2015-01-03 06:05:02 +01:00
|
|
|
|
n
|
|
|
|
|
(+ (fib (- n 1)) (fib (- n 2)))
|
2015-01-03 04:56:07 +01:00
|
|
|
|
)
|
2015-01-03 06:05:02 +01:00
|
|
|
|
) ; GAH, BURN IT WITH FIRE
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
|
|
|
|
|
2015-01-03 05:25:07 +01:00
|
|
|
|
+ Inline comments shall be two spaces from the end of the code; they
|
2015-01-03 04:56:07 +01:00
|
|
|
|
must always have a space between the comment character and the start
|
2015-01-03 05:25:07 +01:00
|
|
|
|
of the comment. Also, try to not comment the obvious.
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
|
|
|
|
.. code-block:: clj
|
|
|
|
|
|
|
|
|
|
;; Good
|
|
|
|
|
(setv ind (dec x)) ; indexing starts from 0
|
|
|
|
|
|
2015-01-03 05:25:07 +01:00
|
|
|
|
;; Style-compliant but just states the obvious
|
2015-01-03 04:56:07 +01:00
|
|
|
|
(setv ind (dec x)) ; sets index to x-1
|
|
|
|
|
|
|
|
|
|
;; Bad
|
|
|
|
|
(setv ind (dec x));typing words for fun
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Coding Style
|
2015-01-03 04:58:46 +01:00
|
|
|
|
============
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
2015-01-03 05:25:07 +01:00
|
|
|
|
+ Do not use s-expression syntax where vector syntax is intended.
|
|
|
|
|
For instance, the fact that the former of these two examples works
|
|
|
|
|
is just because the compiler isn't overly strict. In reality, the
|
|
|
|
|
correct syntax in places such as this is the latter.
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
2015-01-03 06:05:02 +01:00
|
|
|
|
.. code-block:: clj
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
2015-01-03 06:05:02 +01:00
|
|
|
|
;; Bad (and evil)
|
|
|
|
|
(defn foo (x) (print x))
|
|
|
|
|
(foo 1)
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
2015-01-03 06:05:02 +01:00
|
|
|
|
;; Good (and preferred)
|
|
|
|
|
(defn foo [x] (print x))
|
|
|
|
|
(foo 1)
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
|
|
|
|
|
2015-01-03 05:25:07 +01:00
|
|
|
|
+ Use the threading macro or the threading tail macros when encountering
|
|
|
|
|
deeply nested s-expressions. However, be judicious when using them. Do
|
|
|
|
|
use them when clarity and readability improves; do not construct
|
|
|
|
|
convoluted, hard to understand expressions.
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
2015-01-03 06:05:02 +01:00
|
|
|
|
.. code-block:: clj
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
2015-01-03 06:05:02 +01:00
|
|
|
|
;; Preferred
|
2018-01-05 21:51:00 +01:00
|
|
|
|
(setv *names*
|
2015-01-03 06:05:02 +01:00
|
|
|
|
(with [f (open "names.txt")]
|
|
|
|
|
(-> (.read f) (.strip) (.replace "\"" "") (.split ",") (sorted))))
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
2015-01-03 06:05:02 +01:00
|
|
|
|
;; Not so good
|
2018-01-05 21:51:00 +01:00
|
|
|
|
(setv *names*
|
2015-01-03 06:05:02 +01:00
|
|
|
|
(with [f (open "names.txt")]
|
2015-03-13 14:23:38 +01:00
|
|
|
|
(sorted (.split "," (.replace "\"" "" (.strip (.read f)))))))
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
2015-01-03 06:05:02 +01:00
|
|
|
|
;; Probably not a good idea
|
2018-01-05 21:51:00 +01:00
|
|
|
|
(setv square? [x]
|
2015-01-03 06:05:02 +01:00
|
|
|
|
(->> 2 (pow (int (sqrt x))) (= x)))
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
|
|
|
|
|
2015-01-03 05:25:07 +01:00
|
|
|
|
+ Clojure-style dot notation is preferred over the direct call of
|
|
|
|
|
the object's method, though both will continue to be supported.
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
2015-01-03 06:05:02 +01:00
|
|
|
|
.. code-block:: clj
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
2015-01-03 06:05:02 +01:00
|
|
|
|
;; Good
|
|
|
|
|
(with [fd (open "/etc/passwd")]
|
2015-01-03 04:56:07 +01:00
|
|
|
|
(print (.readlines fd)))
|
|
|
|
|
|
2015-01-03 06:05:02 +01:00
|
|
|
|
;; Not so good
|
|
|
|
|
(with [fd (open "/etc/passwd")]
|
2015-01-03 04:56:07 +01:00
|
|
|
|
(print (fd.readlines)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Conclusion
|
2015-01-03 04:58:46 +01:00
|
|
|
|
==========
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
2015-01-03 05:25:07 +01:00
|
|
|
|
“Fashions fade, style is eternal”
|
|
|
|
|
—Yves Saint Laurent
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
|
|
|
|
|
2015-01-03 05:25:07 +01:00
|
|
|
|
This guide is just a set of community guidelines, and 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 most
|
|
|
|
|
importantly, have fun with Hy.
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Thanks
|
2015-01-03 04:58:46 +01:00
|
|
|
|
======
|
2015-01-03 04:56:07 +01:00
|
|
|
|
|
|
|
|
|
+ This guide is heavily inspired from `@paultag`_ 's blog post `Hy
|
|
|
|
|
Survival Guide`_
|
|
|
|
|
+ The `Clojure Style Guide`_
|
|
|
|
|
|
2017-02-07 20:25:40 +01:00
|
|
|
|
.. _`Hy Survival Guide`: https://notes.pault.ag/hy-survival-guide/
|
2015-01-03 04:56:07 +01:00
|
|
|
|
.. _`Clojure Style Guide`: https://github.com/bbatsov/clojure-style-guide
|
|
|
|
|
.. _`@paultag`: https://github.com/paultag
|