diff --git a/README.md b/README.md
index 21aeab4..68180d9 100644
--- a/README.md
+++ b/README.md
@@ -1,38 +1,22 @@
Hy
==
-[![Build Status](https://img.shields.io/travis/hylang/hy/master.svg)](https://travis-ci.org/hylang/hy)
[![Version](https://img.shields.io/pypi/v/hy.svg)](https://pypi.python.org/pypi/hy)
-Lisp and Python should love each other. Let's make it happen. [Try it](http://try-hy.appspot.com/).
+Lisp and Python should love each other. Let's make it happen.
-Hylarious Hacks
----------------
+Hy is a Lisp dialect that's embedded in Python. Since Hy transforms its Lisp
+code into Python abstract syntax tree (AST) objects, you have the whole
+beautiful world of Python at your fingertips, in Lisp form.
-* [Django + Lisp](https://github.com/paultag/djlisp/tree/master/djlisp)
-* [Python `sh` Fun](https://twitter.com/paultag/status/314925996442796032)
-* [Hy IRC Bot](https://github.com/hylang/hygdrop)
-* [miniKanren in Hy](https://github.com/algernon/adderall)
+To install the latest stable release of Hy, just use the command `pip3 install
+--user hy`. Then you can start an interactive read-eval-print loop (REPL) with
+the command `hy`, or run a Hy program with `hy myprogram.hy`.
-OK, so, why?
-------------
-
-Well. Python is awesome. So awesome, that we have so many tools to alter the
-language in a *core* way, but we never use them.
-
-Why?
-
-Well, I wrote Hy to help people realize one thing about Python:
-
-It's really awesome.
-
-Oh, and lisps are neat.
-
-![Cuddles the Hacker](https://i.imgur.com/QbPMXTN.png)
-
-(fan art from the one and only [doctormo](http://doctormo.deviantart.com/art/Cuddles-the-Hacker-372184766))
+* [Why Hy?](http://docs.hylang.org/en/master/whyhy.html)
+* [Tutorial](http://docs.hylang.org/en/master/tutorial.html)
Project
-------
@@ -41,10 +25,13 @@ Project
* Documentation:
* stable, for use with the latest stable release: http://hylang.org/
* master, for use with the latest revision on GitHub: http://docs.hylang.org/en/master
-* Quickstart: http://hylang.org/en/stable/quickstart.html
* Bug reports: We have no bugs! Your bugs are your own! (https://github.com/hylang/hy/issues)
* License: MIT (Expat)
* [Hacking on Hy](http://docs.hylang.org/en/master/hacking.html)
* [Contributor Guidelines](http://docs.hylang.org/en/master/hacking.html#contributor-guidelines)
* [Code of Conduct](http://docs.hylang.org/en/master/hacking.html#contributor-code-of-conduct)
* IRC: Join #hy on [freenode](https://webchat.freenode.net/)
+
+![Cuddles the Hacker](https://i.imgur.com/QbPMXTN.png)
+
+(fan art from the one and only [doctormo](http://doctormo.deviantart.com/art/Cuddles-the-Hacker-372184766))
diff --git a/docs/contrib/walk.rst b/docs/contrib/walk.rst
index 2e36234..e6d333e 100644
--- a/docs/contrib/walk.rst
+++ b/docs/contrib/walk.rst
@@ -206,6 +206,8 @@ Recursively performs all possible macroexpansions in form, using the ``require``
Macros
======
+.. _let:
+
let
---
diff --git a/docs/hacking.rst b/docs/hacking.rst
index da964b5..064159a 100644
--- a/docs/hacking.rst
+++ b/docs/hacking.rst
@@ -1,3 +1,5 @@
+.. _hacking:
+
===============
Hacking on Hy
===============
diff --git a/docs/index.rst b/docs/index.rst
index 4a6cf41..6089770 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -1,36 +1,27 @@
-Welcome to Hy's documentation!
-==============================
+The Hy Manual
+=============
.. image:: _static/hy-logo-small.png
:alt: Hy
:align: left
-:Try Hy: https://try-hy.appspot.com
:PyPI: https://pypi.python.org/pypi/hy
:Source: https://github.com/hylang/hy
:List: `hylang-discuss `_
-:IRC: ``#hy`` on Freenode
-:Build status:
- .. image:: https://secure.travis-ci.org/hylang/hy.png
- :alt: Travis CI
- :target: http://travis-ci.org/hylang/hy
+:IRC: irc://chat.freenode.net/hy
-Hy is a wonderful dialect of Lisp that's embedded in Python.
+Hy is a Lisp dialect that's embedded in Python. Since Hy transforms its Lisp
+code into Python abstract syntax tree (AST) objects, you have the whole
+beautiful world of Python at your fingertips, in Lisp form.
-Since Hy transforms its Lisp code into the Python Abstract Syntax
-Tree, you have the whole beautiful world of Python at your fingertips,
-in Lisp form!
-
-
-Documentation Index
-===================
-
-Contents:
+To install the latest stable release of Hy, just use the command ``pip3 install
+--user hy``. Then you can start an interactive read-eval-print loop (REPL) with
+the command ``hy``, or run a Hy program with ``hy myprogram.hy``.
.. toctree::
:maxdepth: 3
- quickstart
+ whyhy
tutorial
style-guide
language/index
diff --git a/docs/language/api.rst b/docs/language/api.rst
index fd246a0..c4f877b 100644
--- a/docs/language/api.rst
+++ b/docs/language/api.rst
@@ -1,3 +1,5 @@
+.. _special-forms:
+
=================
Built-Ins
=================
@@ -279,6 +281,8 @@ This is completely discarded and doesn't expand to anything, not even ``None``.
Hy
+.. _cond:
+
cond
----
@@ -338,6 +342,8 @@ is only called on every other value in the list.
(side-effect2 x))
+.. _do:
+
do
----------
@@ -400,6 +406,8 @@ the second of which becomes each value.
{0: 0, 1: 10, 2: 20, 3: 30, 4: 40}
+.. _setv:
+
setv
----
@@ -416,20 +424,19 @@ For example:
=> (counter [1 2 3 4 5 2 3] 2)
2
-They can be used to assign multiple variables at once:
+You can provide more than one target–value pair, and the assignments will be made in order::
-.. code-block:: hy
+ (setv x 1 y x x 2)
+ (print x y) ; => 2 1
- => (setv a 1 b 2)
- (1L, 2L)
- => a
- 1L
- => b
- 2L
- =>
+You can perform parallel assignments or unpack the source value with square brackets and :ref:`unpack-iterable`::
+ (setv duo ["tim" "eric"])
+ (setv [guy1 guy2] duo)
+ (print guy1 guy2) ; => tim eric
-``setv`` always returns ``None``.
+ (setv [letter1 letter2 #* others] "abcdefg")
+ (print letter1 letter2 others) ; => a b ['c', 'd', 'e', 'f', 'g']
setx
@@ -444,6 +451,8 @@ Whereas ``setv`` creates an assignment statement, ``setx`` creates an assignment
3 is greater than 0
+.. _defclass:
+
defclass
--------
@@ -914,6 +923,9 @@ raising an exception.
=> (first [])
None
+
+.. _for:
+
for
---
@@ -992,6 +1004,8 @@ written without accidental variable name clashes.
Section :ref:`using-gensym`
+.. _get:
+
get
---
@@ -1022,6 +1036,8 @@ successive elements in a nested structure. Example usage:
index that is out of bounds.
+.. _gfor:
+
gfor
----
@@ -1063,6 +1079,8 @@ keyword, the second function would have raised a ``NameError``.
(set-a 5)
(print-a)
+.. _if:
+
if / if* / if-not
-----------------
@@ -1188,6 +1206,8 @@ that ``import`` can be used.
(import [sys [*]])
+.. _fn:
+
fn
-----------
@@ -1253,6 +1273,8 @@ last
6
+.. _lfor:
+
lfor
----
@@ -1396,6 +1418,8 @@ print
.. note:: ``print`` always returns ``None``.
+.. _quasiquote:
+
quasiquote
----------
@@ -1414,6 +1438,8 @@ using ``unquote`` (``~``). The evaluated form can also be spliced using
; equivalent to '(foo bar baz)
+.. _quote:
+
quote
-----
@@ -1431,6 +1457,8 @@ alternatively be written using the apostrophe (``'``) symbol.
Hello World
+.. _require:
+
require
-------
@@ -1571,6 +1599,8 @@ sfor
equivalent to ``(set (lfor CLAUSES VALUE))``. See `lfor`_.
+.. _cut:
+
cut
-----
@@ -1677,6 +1707,8 @@ the given conditional is ``False``. The following shows the expansion of this ma
(do statement))
+.. _unpack-iterable:
+
unpack-iterable, unpack-mapping
-------------------------------
@@ -1717,6 +1749,8 @@ more than once in one expression (:pep:`3132`, :pep:`448`).
[1, 2, 3, 4]
+.. _unquote:
+
unquote
-------
@@ -1792,6 +1826,8 @@ following shows the expansion of the macro.
(if conditional (do statement))
+.. _while:
+
while
-----
@@ -1851,6 +1887,9 @@ prints
In condition
At end of outer loop
+
+.. _with:
+
with
----
diff --git a/docs/language/interop.rst b/docs/language/interop.rst
index 6276659..cb009b4 100644
--- a/docs/language/interop.rst
+++ b/docs/language/interop.rst
@@ -1,3 +1,5 @@
+.. _interop:
+
=====================
Hy <-> Python interop
=====================
diff --git a/docs/language/syntax.rst b/docs/language/syntax.rst
index 16ed838..2e2e60a 100644
--- a/docs/language/syntax.rst
+++ b/docs/language/syntax.rst
@@ -1,3 +1,5 @@
+.. _syntax:
+
==============
Syntax
==============
diff --git a/docs/quickstart.rst b/docs/quickstart.rst
deleted file mode 100644
index ca00c73..0000000
--- a/docs/quickstart.rst
+++ /dev/null
@@ -1,54 +0,0 @@
-==========
-Quickstart
-==========
-
-.. image:: _static/cuddles-transparent-small.png
- :alt: Karen Rustard's Cuddles
-
-(Thanks to Karen Rustad for Cuddles!)
-
-
-**HOW TO GET HY REAL FAST**:
-
-1. Create a `Virtual Python Environment
- `_.
-2. Activate your Virtual Python Environment.
-3. Install `hy from GitHub `_ with ``$ pip install git+https://github.com/hylang/hy.git``.
-4. Start a REPL with ``hy``.
-5. Type stuff in the REPL::
-
- => (print "Hy!")
- Hy!
- => (defn salutationsnm [name] (print (+ "Hy " name "!")))
- => (salutationsnm "YourName")
- Hy YourName!
-
- etc
-
-6. Hit CTRL-D when you're done.
-7. If you're familiar with Python, start the REPL using ``hy --spy`` to check what happens inside::
-
- => (+ "Hyllo " "World" "!")
- 'Hyllo ' + 'World' + '!'
-
- 'Hyllo World!'
-
-*OMG! That's amazing! I want to write a Hy program.*
-
-8. Open up an elite programming editor and type::
-
- #! /usr/bin/env hy
- (print "I was going to code in Python syntax, but then I got Hy.")
-
-9. Save as ``awesome.hy``.
-10. Make it executable::
-
- chmod +x awesome.hy
-
-11. And run your first Hy program::
-
- ./awesome.hy
-
-12. Take a deep breath so as to not hyperventilate.
-13. Smile villainously and sneak off to your hydeaway and do
- unspeakable things.
diff --git a/docs/tutorial.rst b/docs/tutorial.rst
index e7dfa44..566417a 100644
--- a/docs/tutorial.rst
+++ b/docs/tutorial.rst
@@ -2,272 +2,174 @@
Tutorial
========
-.. TODO
-..
-.. - How do I index into arrays or dictionaries?
-.. - Blow your mind with macros!
-.. - Where's my banana???
+.. image:: _static/cuddles-transparent-small.png
+ :alt: Karen Rustard's Cuddles
-Welcome to the Hy tutorial!
+This chapter provides a quick introduction to Hy. It assumes a basic background
+in programming, but no specific prior knowledge of Python or Lisp.
-In a nutshell, Hy is a Lisp dialect, but one that converts its
-structure into Python ... literally a conversion into Python's abstract
-syntax tree! (Or to put it in more crude terms, Hy is lisp-stick on a
-Python!)
+Lisp-stick on a Python
+======================
-This is pretty cool because it means Hy is several things:
+Let's start with the classic::
- - A Lisp that feels very Pythonic
- - For Lispers, a great way to use Lisp's crazy powers but in the wide
- world of Python's libraries (why yes, you now can write a Django
- application in Lisp!)
- - For Pythonistas, a great way to start exploring Lisp, from the
- comfort of Python!
- - For everyone: a pleasant language that has a lot of neat ideas!
+ (print "Hy, world!")
+This program calls the :func:`print` function, which, like all of Python's
+:ref:`built-in functions `, is available in Hy.
-Basic intro to Lisp for Pythonistas
-===================================
+All of Python's :ref:`binary and unary operators ` are
+available, too, although ``==`` is spelled ``=`` in deference to Lisp
+tradition. Here's how we'd use the addition operator ``+``::
-Okay, maybe you've never used Lisp before, but you've used Python!
+ (+ 1 3)
-A "hello world" program in Hy is actually super simple. Let's try it:
+This code returns ``4``. It's equivalent to ``1 + 3`` in Python and many other
+languages. Languages in the `Lisp
+`_ family, including
+Hy, use a prefix syntax: ``+``, just like ``print`` or ``sqrt``, appears before
+all of its arguments. The call is delimited by parentheses, but the opening
+parenthesis appears before the operator being called instead of after it, so
+instead of ``sqrt(2)``, we write ``(sqrt 2)``. Multiple arguments, such as the
+two integers in ``(+ 1 3)``, are separated by whitespace. Many operators,
+including ``+``, allow more than two arguments: ``(+ 1 2 3)`` is equivalent to
+``1 + 2 + 3``.
-.. code-block:: clj
+Here's a more complex example::
- (print "hello world")
+ (- (* (+ 1 3 88) 2) 8)
-See? Easy! As you may have guessed, this is the same as the Python
-version of::
+This code returns ``176``. Why? We can see the infix equivalent with the
+command ``echo "(- (* (+ 1 3 88) 2) 8)" | hy2py``, which returns the Python
+code corresponding to the given Hy code, or by passing the ``--spy`` option to
+Hy when starting the REPL, which shows the Python equivalent of each input line
+before the result. The infix equivalent in this case is:
- print("hello world")
+.. code-block:: python
-To add up some super simple math, we could do:
+ ((1 + 3 + 88) * 2) - 8
-.. code-block:: clj
+To evaluate this infix expression, you'd of course evaluate the innermost
+parenthesized expression first and work your way outwards. The same goes for
+Lisp. Here's what we'd get by evaluating the above Hy code one step at a time::
- (+ 1 3)
+ (- (* (+ 1 3 88) 2) 8)
+ (- (* 92 2) 8)
+ (- 184 8)
+ 176
-Which would return 4 and would be the equivalent of:
+The basic unit of Lisp syntax, which is similar to a C or Python expression, is
+the **form**. ``92``, ``*``, and ``(* 92 2)`` are all forms. A Lisp program
+consists of a sequence of forms nested within forms. Forms are typically
+separated from each other by whitespace, but some forms, such as string
+literals (``"Hy, world!"``), can contain whitespace themselves. An
+**expression** is a form enclosed in parentheses; its first child form, called
+the **head**, determines what the expression does, and should generally be a
+function, macro, or special operator. Functions are the most ordinary sort of
+head, whereas macros (described in more detail below) are functions executed at
+compile-time instead and return code to be executed at run-time. Special
+operators are one of :ref:`a fixed set of names ` that are
+hard-coded into the compiler, and used to implement everything else.
-.. code-block:: clj
+Comments start with a ``;`` character and continue till the end of the line. A
+comment is functionally equivalent to whitespace. ::
- 1 + 3
+ (print (** 2 64)) ; Max 64-bit unsigned integer value
-What you'll notice is that the first item in the list is the function
-being called and the rest of the arguments are the arguments being
-passed in. In fact, in Hy (as with most Lisps) we can pass in
-multiple arguments to the plus operator:
+Although ``#`` isn't a comment character in Hy, a Hy program can begin with a
+`shebang line `_, which Hy itself
+will ignore::
-.. code-block:: clj
+ #!/usr/bin/env hy
+ (print "Make me executable, and run me!")
- (+ 1 3 55)
+Literals
+========
-Which would return 59.
+Hy has :ref:`literal syntax ` for all of the same data types that
+Python does. Here's an example of Hy code for each type and the Python
+equivalent.
-Maybe you've heard of Lisp before but don't know much about it. Lisp
-isn't as hard as you might think, and Hy inherits from Python, so Hy
-is a great way to start learning Lisp. The main thing that's obvious
-about Lisp is that there's a lot of parentheses. This might seem
-confusing at first, but it isn't so hard. Let's look at some simple
-math that's wrapped in a bunch of parentheses that we could enter into
-the Hy interpreter:
+============== ================ =================
+Hy Python Type
+============== ================ =================
+``1`` ``1`` :class:`int`
+``1.2`` ``1.2`` :class:`float`
+``4j`` ``4j`` :class:`complex`
+``True`` ``True`` :class:`bool`
+``None`` ``None`` :class:`NoneType`
+``"hy"`` ``'hy'`` :class:`str`
+``b"hy"`` ``b'hy'`` :class:`bytes`
+``(, 1 2 3)`` ``(1, 2, 3)`` :class:`tuple`
+``[1 2 3]`` ``[1, 2, 3]`` :class:`list`
+``#{1 2 3}`` ``{1, 2, 3}`` :class:`set`
+``{1 2 3 4}`` ``{1: 2, 3: 4}`` :class:`dict`
+============== ================ =================
-.. code-block:: clj
+In addition, Hy has a Clojure-style literal syntax for
+:class:`fractions.Fraction`: ``1/3`` is equivalent to ``fractions.Fraction(1,
+3)``.
- (setv result (- (/ (+ 1 3 88) 2) 8))
-
-This would return 38.0 But why? Well, we could look at the equivalent
-expression in python::
-
- result = ((1 + 3 + 88) / 2) - 8
-
-If you were to try to figure out how the above were to work in python,
-you'd of course figure out the results by solving each inner
-parenthesis. That's the same basic idea in Hy. Let's try this
-exercise first in Python::
-
- result = ((1 + 3 + 88) / 2) - 8
- # simplified to...
- result = (92 / 2) - 8
- # simplified to...
- result = 46.0 - 8
- # simplified to...
- result = 38.0
-
-Now let's try the same thing in Hy:
-
-.. code-block:: clj
-
- (setv result (- (/ (+ 1 3 88) 2) 8))
- ; simplified to...
- (setv result (- (/ 92 2) 8))
- ; simplified to...
- (setv result (- 46.0 8))
- ; simplified to...
- (setv result 38.0)
-
-As you probably guessed, this last expression with ``setv`` means to
-assign the variable "result" to 38.0.
-
-See? Not too hard!
-
-This is the basic premise of Lisp. Lisp stands for "list
-processing"; this means that the structure of the program is
-actually lists of lists. (If you're familiar with Python lists,
-imagine the entire same structure as above but with square brackets
-instead, and you'll be able to see the structure above as both a
-program and a data structure.) This is easier to understand with more
-examples, so let's write a simple Python program, test it, and then
-show the equivalent Hy program::
-
- def simple_conversation():
- print("Hello! I'd like to get to know you. Tell me about yourself!")
- name = input("What is your name? ")
- age = input("What is your age? ")
- print("Hello " + name + "! I see you are " + age + " years old.")
-
- simple_conversation()
-
-If we ran this program, it might go like::
-
- Hello! I'd like to get to know you. Tell me about yourself!
- What is your name? Gary
- What is your age? 38
- Hello Gary! I see you are 38 years old.
-
-Now let's look at the equivalent Hy program:
-
-.. code-block:: clj
-
- (defn simple-conversation []
- (print "Hello! I'd like to get to know you. Tell me about yourself!")
- (setv name (input "What is your name? "))
- (setv age (input "What is your age? "))
- (print (+ "Hello " name "! I see you are "
- age " years old.")))
-
- (simple-conversation)
-
-If you look at the above program, as long as you remember that the
-first element in each list of the program is the function (or
-macro... we'll get to those later) being called and that the rest are
-the arguments, it's pretty easy to figure out what this all means.
-(As you probably also guessed, ``defn`` is the Hy method of defining
-methods.)
-
-Still, lots of people find this confusing at first because there's so
-many parentheses, but there are plenty of things that can help make
-this easier: keep indentation nice and use an editor with parenthesis
-matching (this will help you figure out what each parenthesis pairs up
-with) and things will start to feel comfortable.
-
-There are some advantages to having a code structure that's actually a
-very simple data structure as the core of Lisp is based on. For one
-thing, it means that your programs are easy to parse and that the
-entire actual structure of the program is very clearly exposed to you.
-(There's an extra step in Hy where the structure you see is converted
-to Python's own representations ... in "purer" Lisps such as Common
-Lisp or Emacs Lisp, the data structure you see in the code and the
-data structure that is executed is much more literally close.)
-
-Another implication of this is macros: if a program's structure is a
-simple data structure, that means you can write code that can write
-code very easily, meaning that implementing entirely new language
-features can be very fast. Previous to Hy, this wasn't very possible
-for Python programmers ... now you too can make use of macros'
-incredible power (just be careful to not aim them footward)!
-
-
-Hy is a Lisp-flavored Python
-============================
-
-Hy converts to Python's own abstract syntax tree, so you'll soon start
-to find that all the familiar power of python is at your fingertips.
-
-You have full access to Python's data types and standard library in
-Hy. Let's experiment with this in the hy interpreter::
+The Hy REPL prints output in Python syntax by default::
=> [1 2 3]
[1, 2, 3]
- => {"dog" "bark"
- ... "cat" "meow"}
- {'dog': 'bark', 'cat': 'meow'}
- => (, 1 2 3)
- (1, 2, 3)
- => #{3 1 2}
- {1, 2, 3}
- => 1/2
- Fraction(1, 2)
-Notice the last two lines: Hy has a fraction literal like Clojure.
-
-If you start Hy like this (a shell alias might be helpful)::
+But if you start Hy like this (a shell alias might be helpful)::
$ hy --repl-output-fn=hy.contrib.hy-repr.hy-repr
-the interactive mode will use :ref:`hy-repr-fn` instead of Python's
-native ``repr`` function to print out values, so you'll see values in
-Hy syntax rather than Python syntax::
+the interactive mode will use :ref:`hy-repr-fn` instead of Python's native
+``repr`` function to print out values, so you'll see values in Hy syntax::
=> [1 2 3]
[1 2 3]
- => {"dog" "bark"
- ... "cat" "meow"}
- {"dog" "bark" "cat" "meow"}
-If you are familiar with other Lisps, you may be interested that Hy
-supports the Common Lisp method of quoting:
-.. code-block:: clj
+Basic operations
+================
- => '(1 2 3)
- (1 2 3)
+Set variables with :ref:`setv`::
-You also have access to all the built-in types' nice methods::
+ (setv zone-plane 8)
- => (.strip " fooooo ")
- "fooooo"
+Access the elements of a list, dictionary, or other data structure with
+:ref:`get`::
-What's this? Yes indeed, this is precisely the same as::
+ (setv fruit ["apple" "banana" "cantaloupe"])
+ (print (get fruit 0)) ; => apple
+ (setv (get fruit 1) "durian")
+ (print (get fruit 1)) ; => durian
- " fooooo ".strip()
+Access a range of elements in an ordered structure with :ref:`cut`::
-That's right---Lisp with dot notation! If we have this string
-assigned as a variable, we can also do the following:
+ (print (cut "abcdef" 1 4)) ; => bcd
-.. code-block:: clj
+Conditional logic can be built with :ref:`if`::
- (setv this-string " fooooo ")
- (this-string.strip)
+ (if (= 1 1)
+ (print "Math works. The universe is safe.")
+ (print "Math has failed. The universe is doomed."))
-What about conditionals?:
+As in this example, ``if`` is called like ``(if CONDITION THEN ELSE)``. It
+executes and returns the form ``THEN`` if ``CONDITION`` is true (according to
+:class:`bool`) and ``ELSE`` otherwise. If ``ELSE`` is omitted, ``None`` is used
+in its place.
-.. code-block:: clj
+What if you want to use more than form in place of the ``THEN`` or ``ELSE``
+clauses, or in place of ``CONDITION``, for that matter? Use the special
+operator :ref:`do` (known more traditionally in Lisp as ``progn``), which
+combines several forms into one, returning the last::
- (if (try-some-thing)
- (print "this is if true")
- (print "this is if false"))
+ (if (do (print "Let's check.") (= 1 1))
+ (do
+ (print "Math works.")
+ (print "The universe is safe."))
+ (do
+ (print "Math has failed.")
+ (print "The universe is doomed.")))
-As you can tell above, the first argument to ``if`` is a truth test, the
-second argument is the body if true, and the third argument (optional!)
-is if false (ie. ``else``).
-
-If you need to do more complex conditionals, you'll find that you
-don't have ``elif`` available in Hy. Instead, you should use something
-called ``cond``. In Python, you might do something like::
-
- somevar = 33
- if somevar > 50:
- print("That variable is too big!")
- elif somevar < 10:
- print("That variable is too small!")
- else:
- print("That variable is jussssst right!")
-
-In Hy, you would do:
-
-.. code-block:: clj
+For branching on more than one case, try :ref:`cond`::
(setv somevar 33)
(cond
@@ -278,306 +180,140 @@ In Hy, you would do:
[True
(print "That variable is jussssst right!")])
-What you'll notice is that ``cond`` switches off between a statement
-that is executed and checked conditionally for true or falseness, and
-then a bit of code to execute if it turns out to be true. You'll also
-notice that the ``else`` is implemented at the end simply by checking
-for ``True`` -- that's because ``True`` will always be true, so if we get
-this far, we'll always run that one!
+The macro ``(when CONDITION THEN-1 THEN-2 …)`` is shorthand for ``(if CONDITION
+(do THEN-1 THEN-2 …))``. ``unless`` works the same as ``when``, but inverts the
+condition with ``not``.
-You might notice above that if you have code like:
+Hy's basic loops are :ref:`while` and :ref:`for`::
-.. code-block:: clj
+ (setv x 3)
+ (while (> x 0)
+ (print x)
+ (setv x (- x 1))) ; => 3 2 1
- (if some-condition
- (body-if-true)
- (body-if-false))
+ (for [x [1 2 3]]
+ (print x)) ; => 1 2 3
-But wait! What if you want to execute more than one statement in the
-body of one of these?
+A more functional way to iterate is provided by the comprehension forms such as
+:ref:`lfor`. Whereas ``for`` always returns ``None``, ``lfor`` returns a list
+with one element per iteration. ::
-You can do the following:
+ (print (lfor x [1 2 3] (* x 2))) ; => [2, 4, 6]
-.. code-block:: clj
- (if (try-some-thing)
- (do
- (print "this is if true")
- (print "and why not, let's keep talking about how true it is!"))
- (print "this one's still simply just false"))
+Functions, classes, and modules
+===============================
-You can see that we used ``do`` to wrap multiple statements. If you're
-familiar with other Lisps, this is the equivalent of ``progn``
-elsewhere.
+Define named functions with :ref:`defn`::
-Comments start with semicolons:
+ (defn fib [n]
+ (if (< n 2)
+ n
+ (+ (fib (- n 1)) (fib (- n 2)))))
+ (print (fib 8)) ; => 21
-.. code-block:: clj
+Define anonymous functions with :ref:`fn`::
- (print "this will run")
- ; (print "but this will not")
- (+ 1 2 3) ; we'll execute the addition, but not this comment!
+ (print (list (filter (fn [x] (% x 2)) (range 10))))
+ ; => [1, 3, 5, 7, 9]
-Hashbang (``#!``) syntax is supported:
+Special symbols in the parameter list of ``defn`` or ``fn`` allow you to
+indicate optional arguments, provide default values, and collect unlisted
+arguments::
-.. code-block:: clj
+ (defn test [a b &optional c [d "x"] &rest e]
+ [a b c d e])
+ (print (test 1 2)) ; => [1, 2, None, 'x', ()]
+ (print (test 1 2 3 4 5 6 7)) ; => [1, 2, 3, 4, (5, 6, 7)]
- #! /usr/bin/env hy
- (print "Make me executable, and run me!")
+Set a function parameter by name with a ``:keyword``::
-Looping is not hard but has a kind of special structure. In Python,
-we might do::
+ (test 1 2 :d "y") ; => [1, 2, None, 'y', ()]
- for i in range(10):
- print("'i' is now at " + str(i))
+Define classes with :ref:`defclass`::
-The equivalent in Hy would be:
+ (defclass FooBar []
+ (defn __init__ [self x]
+ (setv self.x x))
+ (defn get-x [self]
+ self.x))
-.. code-block:: clj
+Here we create a new instance ``fb`` of ``FooBar`` and access its attributes by
+various means::
- (for [i (range 10)]
- (print (+ "'i' is now at " (str i))))
+ (setv fb (FooBar 15))
+ (print fb.x) ; => 15
+ (print (. fb x)) ; => 15
+ (print (.get-x fb)) ; => 15
+ (print (fb.get-x)) ; => 15
-Python's collections indexes and slices are implemented
-by the ``get`` and ``cut`` built-in:
+Note that syntax like ``fb.x`` and ``fb.get-x`` only works when the object
+being invoked (``fb``, in this case) is a simple variable name. To get an
+attribute or call a method of an arbitrary form ``FORM``, you must use the
+syntax ``(. FORM x)`` or ``(.get-x FORM)``.
-.. code-block:: clj
+Access an external module, whether written in Python or Hy, with
+:ref:`import`::
- (setv array [0 1 2])
- (get array 1)
- (cut array -3 -1)
+ (import math)
+ (print (math.sqrt 2)) ; => 1.4142135623730951
-which is equivalent to::
-
- array[1]
- array[-3:-1]
-
-You can also import and make use of various Python libraries. For
-example:
-
-.. code-block:: clj
-
- (import os)
-
- (if (os.path.isdir "/tmp/somedir")
- (os.mkdir "/tmp/somedir/anotherdir")
- (print "Hey, that path isn't there!"))
-
-Python's context managers (``with`` statements) are used like this:
-
-.. code-block:: clj
-
- (with [f (open "/tmp/data.in")]
- (print (.read f)))
-
-which is equivalent to::
-
- with open("/tmp/data.in") as f:
- print(f.read())
-
-And yes, we do have List comprehensions! In Python you might do::
-
- odds_squared = [
- pow(num, 2)
- for num in range(100)
- if num % 2 == 1]
-
-In Hy, you could do these like:
-
-.. code-block:: clj
-
- (setv odds-squared
- (lfor
- num (range 100)
- :if (= (% num 2) 1)
- (pow num 2)))
-
-.. code-block:: clj
-
- ; And, an example stolen shamelessly from a Clojure page:
- ; Let's list all the blocks of a Chessboard:
-
- (lfor
- x (range 8)
- y "ABCDEFGH"
- (, x y))
-
- ; [(0, 'A'), (0, 'B'), (0, 'C'), (0, 'D'), (0, 'E'), (0, 'F'), (0, 'G'), (0, 'H'),
- ; (1, 'A'), (1, 'B'), (1, 'C'), (1, 'D'), (1, 'E'), (1, 'F'), (1, 'G'), (1, 'H'),
- ; (2, 'A'), (2, 'B'), (2, 'C'), (2, 'D'), (2, 'E'), (2, 'F'), (2, 'G'), (2, 'H'),
- ; (3, 'A'), (3, 'B'), (3, 'C'), (3, 'D'), (3, 'E'), (3, 'F'), (3, 'G'), (3, 'H'),
- ; (4, 'A'), (4, 'B'), (4, 'C'), (4, 'D'), (4, 'E'), (4, 'F'), (4, 'G'), (4, 'H'),
- ; (5, 'A'), (5, 'B'), (5, 'C'), (5, 'D'), (5, 'E'), (5, 'F'), (5, 'G'), (5, 'H'),
- ; (6, 'A'), (6, 'B'), (6, 'C'), (6, 'D'), (6, 'E'), (6, 'F'), (6, 'G'), (6, 'H'),
- ; (7, 'A'), (7, 'B'), (7, 'C'), (7, 'D'), (7, 'E'), (7, 'F'), (7, 'G'), (7, 'H')]
-
-
-Python has support for various fancy argument and keyword arguments.
-In Python we might see::
-
- >>> def optional_arg(pos1, pos2, keyword1=None, keyword2=42):
- ... return [pos1, pos2, keyword1, keyword2]
- ...
- >>> optional_arg(1, 2)
- [1, 2, None, 42]
- >>> optional_arg(1, 2, 3, 4)
- [1, 2, 3, 4]
- >>> optional_arg(keyword1=1, pos2=2, pos1=3, keyword2=4)
- [3, 2, 1, 4]
-
-The same thing in Hy::
-
- => (defn optional-arg [pos1 pos2 &optional keyword1 [keyword2 42]]
- ... [pos1 pos2 keyword1 keyword2])
- => (optional-arg 1 2)
- [1 2 None 42]
- => (optional-arg 1 2 3 4)
- [1 2 3 4]
-
-You can call keyword arguments like this::
-
- => (optional-arg :keyword1 1
- ... :pos2 2
- ... :pos1 3
- ... :keyword2 4)
- [3, 2, 1, 4]
-
-You can unpack arguments with the syntax ``#* args`` and ``#** kwargs``,
-similar to `*args` and `**kwargs` in Python::
-
- => (setv args [1 2])
- => (setv kwargs {"keyword2" 3
- ... "keyword1" 4})
- => (optional-arg #* args #** kwargs)
- [1, 2, 4, 3]
-
-Hy also supports ``*args`` and ``**kwargs`` in parameter lists. In Python::
-
- def some_func(foo, bar, *args, **kwargs):
- import pprint
- pprint.pprint((foo, bar, args, kwargs))
-
-The Hy equivalent:
-
-.. code-block:: clj
-
- (defn some-func [foo bar &rest args &kwargs kwargs]
- (import pprint)
- (pprint.pprint (, foo bar args kwargs)))
-
-Finally, of course we need classes! In Python, we might have a class
-like::
-
- class FooBar(object):
- """
- Yet Another Example Class
- """
- def __init__(self, x):
- self.x = x
-
- def get_x(self):
- """
- Return our copy of x
- """
- return self.x
-
-And we might use it like::
-
- bar = FooBar(1)
- print(bar.get_x())
-
-
-In Hy:
-
-.. code-block:: clj
-
- (defclass FooBar [object]
- "Yet Another Example Class"
-
- (defn --init-- [self x]
- (setv self.x x))
-
- (defn get-x [self]
- "Return our copy of x"
- self.x))
-
-And we can use it like:
-
-.. code-block:: clj
-
- (setv bar (FooBar 1))
- (print (bar.get-x))
-
-Or using the leading dot syntax!
-
-.. code-block:: clj
-
- (print (.get-x (FooBar 1)))
-
-
-You can also do class-level attributes. In Python::
-
- class Customer(models.Model):
- name = models.CharField(max_length=255)
- address = models.TextField()
- notes = models.TextField()
-
-In Hy:
-
-.. code-block:: clj
-
- (defclass Customer [models.Model]
- (setv name (models.CharField :max-length 255))
- (setv address (models.TextField))
- (setv notes (models.TextField)))
+Python can import a Hy module like any other module so long as Hy itself has
+been imported first, which, of course, must have already happened if you're
+running a Hy program.
Macros
======
-One really powerful feature of Hy are macros. They are small functions that are
-used to generate code (or data). When a program written in Hy is started, the
-macros are executed and their output is placed in the program source. After this,
-the program starts executing normally. Very simple example:
+Macros are the basic metaprogramming tool of Lisp. A macro is a function that
+is called at compile time (i.e., when a Hy program is being translated to
+Python :mod:`ast` objects) and returns code, which becomes part of the final
+program. Here's a simple example::
-.. code-block:: clj
+ (print "Executing")
+ (defmacro m []
+ (print "Now for a slow computation")
+ (setv x (% (** 10 10 7) 3))
+ (print "Done computing")
+ x)
+ (print "Value:" (m))
+ (print "Done executing")
- => (defmacro hello [person]
- ... `(print "Hello there," ~person))
- => (hello "Tuukka")
- Hello there, Tuukka
+If you run this program twice in a row, you'll see this::
-The thing to notice here is that hello macro doesn't output anything on
-screen. Instead it creates piece of code that is then executed and prints on
-screen. This macro writes a piece of program that looks like this (provided that
-we used "Tuukka" as parameter):
+ $ hy example.hy
+ Now for a slow computation
+ Done computing
+ Executing
+ Value: 1
+ Done executing
+ $ hy example.hy
+ Executing
+ Value: 1
+ Done executing
-.. code-block:: clj
+The slow computation is performed while compiling the program on its first
+invocation. Only after the whole program is compiled does normal execution
+begin from the top, printing "Executing". When the program is called a second
+time, it is run from the previously compiled bytecode, which is equivalent to
+simply::
- (print "Hello there," "Tuukka")
+ (print "Executing")
+ (print "Value:" 1)
+ (print "Done executing")
-We can also manipulate code with macros:
-
-.. code-block:: clj
-
- => (defmacro rev [code]
- ... (setv op (last code) params (list (butlast code)))
- ... `(~op ~@params))
- => (rev (1 2 3 +))
- 6
-
-The code that was generated with this macro just switched around some of the
-elements, so by the time program started executing, it actually reads:
-
-.. code-block:: clj
-
- (+ 1 2 3)
+Our macro ``m`` has an especially simple return value, an integer, which at
+compile-time is converted to an integer literal. In general, macros can return
+arbitrary Hy forms to be executed as code. There are several special operators
+and macros that make it easy to construct forms programmatically, such as
+:ref:`quote` (``'``), :ref:`quasiquote` (`````), :ref:`unquote` (``~``), and
+:ref:`defmacro!`. The previous chapter has :ref:`a simple example `
+of using ````` and ``~`` to define a new control construct ``do-while``.
Sometimes it's nice to be able to call a one-parameter macro without
-parentheses. Tag macros allow this. The name of a tag macro is typically
-one character long, but since Hy operates well with Unicode, we aren't running
-out of characters that soon:
-
-.. code-block:: clj
+parentheses. Tag macros allow this. The name of a tag macro is often just one
+character long, but since Hy allows most Unicode characters in the name of a
+macro (or ordinary variable), you won't out of characters soon. ::
=> (deftag ↻ [code]
... (setv op (last code) params (list (butlast code)))
@@ -585,106 +321,23 @@ out of characters that soon:
=> #↻(1 2 3 +)
6
-Macros are useful when one wishes to extend Hy or write their own
-language on top of that. Many features of Hy are macros, like ``when``,
-``cond`` and ``->``.
-
-What if you want to use a macro that's defined in a different
-module? The special form ``import`` won't help, because it merely
-translates to a Python ``import`` statement that's executed at
-run-time, and macros are expanded at compile-time, that is,
-during the translate from Hy to Python. Instead, use ``require``,
-which imports the module and makes macros available at
-compile-time. ``require`` uses the same syntax as ``import``.
-
-.. code-block:: clj
+What if you want to use a macro that's defined in a different module?
+``import`` won't help, because it merely translates to a Python ``import``
+statement that's executed at run-time, and macros are expanded at compile-time,
+that is, during the translation from Hy to Python. Instead, use :ref:`require`,
+which imports the module and makes macros available at compile-time.
+``require`` uses the same syntax as ``import``. ::
=> (require tutorial.macros)
=> (tutorial.macros.rev (1 2 3 +))
6
-Hy <-> Python interop
-=====================
+Next steps
+==========
-Using Hy from Python
---------------------
+You now know enough to be dangerous with Hy. You may now smile villainously and
+sneak off to your Hydeaway to do unspeakable things.
-You can use Hy modules in Python!
-
-If you save the following in ``greetings.hy``:
-
-.. code-block:: clj
-
- (defn greet [name] (print "hello from hy," name))
-
-Then you can use it directly from Python, by importing Hy before importing
-the module. In Python::
-
- import hy
- import greetings
-
- greetings.greet("Foo")
-
-Using Python from Hy
---------------------
-
-You can also use any Python module in Hy!
-
-If you save the following in ``greetings.py`` in Python::
-
- def greet(name):
- print("hello, %s" % (name))
-
-You can use it in Hy (see :ref:`import`):
-
-.. code-block:: clj
-
- (import greetings)
- (.greet greetings "foo")
-
-More information on :doc:`../language/interop`.
-
-
-Protips!
-========
-
-Hy also features something known as the "threading macro", a really neat
-feature of Clojure's. The "threading macro" (written as ``->``) is used
-to avoid deep nesting of expressions.
-
-The threading macro inserts each expression into the next expression's first
-argument place.
-
-Let's take the classic:
-
-.. code-block:: clj
-
- (require [hy.contrib.loop [loop]])
-
- (loop (print (eval (read))))
-
-Rather than write it like that, we can write it as follows:
-
-.. code-block:: clj
-
- (require [hy.contrib.loop [loop]])
-
- (-> (read) (eval) (print) (loop))
-
-Now, using `python-sh `_, we can show
-how the threading macro (because of python-sh's setup) can be used like
-a pipe:
-
-.. code-block:: clj
-
- => (import [sh [cat grep wc]])
- => (-> (cat "/usr/share/dict/words") (grep "-E" "^hy") (wc "-l"))
- 210
-
-Which, of course, expands out to:
-
-.. code-block:: clj
-
- (wc (grep (cat "/usr/share/dict/words") "-E" "^hy") "-l")
-
-Much more readable, no? Use the threading macro!
+Refer to Python's documention for the details of Python semantics, and the rest
+of this manual for Hy-specific features. Like Hy itself, the manual is
+incomplete, but :ref:`contributions ` are always welcome.
diff --git a/docs/whyhy.rst b/docs/whyhy.rst
new file mode 100644
index 0000000..55ad8bc
--- /dev/null
+++ b/docs/whyhy.rst
@@ -0,0 +1,142 @@
+=======
+Why Hy?
+=======
+
+Hy is a multi-paradigm general-purpose programming language in the `Lisp family
+`_. It's implemented
+as a kind of alternative syntax for Python. Compared to Python, Hy offers a
+variety of extra features, generalizations, and syntactic simplifications, as
+would be expected of a Lisp. Compared to other Lisps, Hy provides direct access
+to Python's built-ins and third-party Python libraries, while allowing you to
+freely mix imperative, functional, and object-oriented styles of programming.
+
+
+Hy versus Python
+----------------
+
+The first thing a Python programmer will notice about Hy is that it has Lisp's
+traditional parenthesis-heavy prefix syntax in place of Python's C-like infix
+syntax. For example, ``print("The answer is", 2 + object.method(arg))`` could
+be written ``(print "The answer is" (+ 2 (.method object arg)))`` in Hy.
+Consequently, Hy is free-form: structure is indicated by parentheses rather
+than whitespace, making it convenient for command-line use.
+
+As in other Lisps, the value of a simplistic syntax is that it facilitates
+Lisp's signature feature: `metaprogramming
+`_ through macros, which are
+functions that manipulate code objects at compile time to produce new code
+objects, which are then executed as if they had been part of the original code.
+In fact, Hy allows arbitrary computation at compile-time. For example, here's a
+simple macro that implements a C-style do-while loop, which executes its body
+for as long as the condition is true, but at least once.
+
+.. _do-while:
+
+::
+
+ (defmacro do-while [condition &rest body]
+ `(do
+ ~body
+ (while ~condition
+ ~body)))
+
+ (setv x 0)
+ (do-while x
+ (print "This line is executed once."))
+
+Hy also removes Python's restrictions on mixing expressions and statements,
+allowing for more direct and functional code. For example, Python doesn't allow
+:ref:`with ` blocks, which close a resource once you're done using it,
+to return values. They can only execute a set of statements:
+
+.. code-block:: python
+
+ with open("foo") as o:
+ f1 = o.read()
+ with open("bar") as o:
+ f2 = o.read()
+ print(len(f1) + len(f2))
+
+In Hy, :ref:`with` returns the value of its last body form, so you can use it
+like an ordinary function call::
+
+ (print (+
+ (len (with [o (open "foo")] (.read o))
+ (len (with [o (open "bar")] (.read o))))))
+
+To be even more concise, you can put a ``with`` form in a :ref:`generator
+expression `::
+
+ (print (sum (gfor
+ filename ["foo" "bar"]
+ (len (with [o (open filename)] (.read o))))))
+
+Finally, Hy offers several generalizations to Python's binary operators.
+Operators can be given more than two arguments (e.g., ``(+ 1 2 3)``), including
+augmented assignment operators (e.g., ``(+= x 1 2 3)``). They are also provided
+as ordinary first-class functions of the same name, allowing them to be passed
+to higher-order functions: ``(sum xs)`` could be written ``(reduce + xs)``.
+
+The Hy compiler works by reading Hy source code into Hy model objects and
+compiling the Hy model objects into Python abstract syntax tree (:py:mod:`ast`)
+objects. Python AST objects can then be compiled and run by Python itself,
+byte-compiled for faster execution later, or rendered into Python source code.
+You can even :ref:`mix Python and Hy code in the same project `, which
+can be a good way to get your feet wet in Hy.
+
+
+Hy versus other Lisps
+---------------------
+
+At run-time, Hy is essentially Python code. Thus, while Hy's design owes a lot
+to `Clojure `_, it is more tightly coupled to Python than
+Clojure is to Java; a better analogy is `CoffeeScript's
+`_ relationship to JavaScript. Python's built-in
+:ref:`functions ` and :ref:`data structures
+` are directly available::
+
+ (print (int "deadbeef" :base 16)) ; 3735928559
+ (print (len [1 10 100])) ; 3
+
+The same goes for third-party Python libraries from `PyPI `_
+and elsewhere. Here's a tiny `CherryPy `_ web application
+in Hy::
+
+ (import cherrypy)
+
+ (defclass HelloWorld []
+ (#@ cherrypy.expose (defn index [self]
+ "Hello World!")))
+
+ (cherrypy.quickstart (HelloWorld))
+
+You can even run Hy on `PyPy `_ for a particularly speedy
+Lisp.
+
+Like all Lisps, Hy is `homoiconic
+`_. Its syntax is represented not
+with cons cells or with Python's basic data structures, but with simple
+subclasses of Python's basic data structures called :ref:`models `.
+Using models in place of plain ``list``\s, ``set``\s, and so on has two
+purposes: models can keep track of their line and column numbers for the
+benefit of error messages, and models can represent syntactic features that the
+corresponding primitive type can't, such as the order in which elements appear
+in a set literal. However, models can be concatenated and indexed just like
+plain lists, and you can return ordinary Python types from a macro or give them
+to ``eval`` and Hy will automatically promote them to models.
+
+Hy takes much of its semantics from Python. For example, Hy is a Lisp-1 because
+Python functions use the same namespace as objects that aren't functions. In
+general, any Python code should be possible to literally translate to Hy. At
+the same time, Hy goes to some lengths to allow you to do typical Lisp things
+that aren't straightforward in Python. For example, Hy provides the
+aforementioned mixing of statements and expressions, :ref:`name mangling
+` that transparently converts symbols with names like ``valid?`` to
+Python-legal identifiers, and a :ref:`let` macro to provide block-level scoping
+in place of Python's usual function-level scoping.
+
+Overall, Hy, like Common Lisp, is intended to be an unopinionated big-tent
+language that lets you do what you want. If you're interested in a more
+small-and-beautiful approach to Lisp, in the style of Scheme, check out
+`Hissp `_, another Lisp embedded in Python
+that was created by a Hy developer.