Technical Documentation: hylang/hy
ℹ️ Provenance: Multi-Tier Ingestion · CodeWiki Reference
Api (`docs/api.rst`)
API reference
This chapter describes most of Hy's public-facing macros, functions, and
classes. It refers to Python's own documentation when appropriate
rather than recapitulating the details of Python semantics.
.. contents:: Contents
:local:
.. _core-macros:
Core macros
The following macros are automatically imported into all Hy modules as their
base names, such that hy.core.macros.foo can be called as just foo.
Macros that are also available as functions are described as functions
under :ref:pyop.
Fundamentals
.. hy:macro:: (do [#* body])
``do`` (called ``progn`` in some Lisps) takes any number of forms,
evaluates them, and returns the value of the last one, or ``None`` if no
forms were provided. ::
(+ 1 (do (setv x (+ 1 1)) x)) ; => 3
.. hy:macro:: (do-mac [#* body])
``do-mac`` evaluates its arguments (in order) at compile time, and leaves behind the value of the last argument (``None`` if no arguments were provided) as code to be run. The effect is similar to defining and then immediately calling a nullary macro, hence the name, which stands for "do macro". ::
(do-mac `(setv ~(hy.models.Symbol (* "x" 5)) "foo"))
; Expands to: (setv xxxxx "foo")
(print xxxxx)
; => "foo"
Contrast with :hy:func:`eval-and-compile`, which evaluates the same code at compile-time and run-time, instead of using the result of the compile-time run as code for run-time. ``do-mac`` is also similar to Common Lisp's SHARPSIGN DOT syntax (``#.``), from which it differs by evaluating at compile-time rather than read-time.
.. hy:macro:: (eval-and-compile [#* body])
``eval-and-compile`` takes any number of forms as arguments. The input forms are evaluated as soon as the ``eval-and-compile`` form is compiled, then left in the program so they can be executed at run-time as usual; contrast with :hy:func:`eval-when-compile`. So, if you compile and immediately execute a program (as calling ``hy foo.hy`` does when ``foo.hy`` doesn't have an up-to-date byte-compiled version), ``eval-and-compile`` forms will be evaluated twice. For example, the following program ::
(eval-when-compile
(print "Compiling"))
(print "Running")
(eval-and-compile
(print "Hi"))
prints
.. code-block:: text
Compiling
Hi
Running
Hi
The return value of ``eval-and-compile`` is its final argument, as for :hy:func:`do`.
One possible use of ``eval-and-compile`` is to make a function available both at compile-time (so a macro can call it while expanding) and run-time (so it can be called like any other function)::
(eval-and-compile
(defn add [x y]
(+ x y)))
(defmacro m [x]
(add x 2))
(print (m 3)) ; prints 5
(print (add 3 6)) ; prints 9
Had the ``defn`` not been wrapped in ``eval-and-compile``, ``m`` wouldn't be able to call ``add``, because when the compiler was expanding ``(m 3)``, ``add`` wouldn't exist yet.
While ``eval-and-compile`` executes the same code at both compile-time and run-time, bear in mind that the same code can have different meanings in the two contexts. Consider, for example, issues of scoping::
(eval-when-compile
(print "Compiling"))
(print "Running")
(eval-and-compile
(setv x 1))
(defn f []
(setv x 2)
(eval-and-compile
(setv x 3))
(print "local x =" x))
(f)
(eval-and-compile
(print "global x =" x))
The form ``(setv x 3)`` above refers to the global ``x`` at compile-time, but the local ``x`` at run-time, so the result is:
.. code-block:: text
Compiling
global x = 3
Running
local x = 3
global x = 1
.. hy:macro:: (eval-when-compile [#* body])
``eval-when-compile`` executes the given forms at compile-time, but discards them at run-time and simply returns :data:`None` instead; contrast :hy:func:`eval-and-compile`. Hence, while ``eval-when-compile`` doesn't directly contribute code to the final program, it can change Hy's state while compiling, as by defining a function::
(eval-when-compile
(defn add [x y]
(+ x y)))
(defmacro m [x]
(add x 2))
(print (m 3)) ; prints 5
(print (add 3 6)) ; raises NameError: name 'add' is not defined
.. hy:macro:: (py [string])
``py`` parses the given Python code at compile-time and inserts the result into
the generated abstract syntax tree. Thus, you can mix Python code into a Hy
program. Only a Python expression is allowed, not statements; use
:hy:func:`pys ` if you want to use Python statements. The value of the
expression is returned from the ``py`` form. ::
(print "A result from Python:" (py "'hello' + 'world'"))
The code must be given as a single string literal, but you can still use
macros, :hy:func:`hy.eval <hy.eval>`, and related tools to construct the ``py`` form. If
having to backslash-escape internal double quotes is getting you down, try a
:ref:`bracket string `. If you want to evaluate some Python
code that's only defined at run-time, try the standard Python function
:func:`eval`.
The code is implicitly wrapped in parentheses so Python won't give you grief
about indentation. After all, Python's indentation rules are only useful for
grouping statements, whereas ``py`` only allows an expression.
Python code need not syntactically round-trip if you use :ref:`hy2py` on a Hy
program that uses ``py`` or ``pys``. For example, comments will be removed.
.. hy:macro:: (pys [string])
As :hy:func:`py `, but the code can consist of zero or more statements,
including compound statements such as ``for`` and ``def``. ``pys`` always
returns ``None``. ::
(pys "myvar = 5")
(print "myvar is" myvar)
Unlike ``py``, no parentheses are added, because Python doesn't allow
statements to be parenthesized. Instead, the code string is dedented with
:func:`textwrap.dedent` before parsing. Thus you can indent the code to
match the surrounding Hy code when Python would otherwise forbid this, but
beware that significant leading whitespace in embedded string literals will
be removed.
.. hy:macro:: (pragma [#* args])
``pragma`` is used to adjust the state of the compiler. It's called for its
side-effects, and returns ``None``. The arguments are key-value pairs, like a
function call with keyword arguments::
(pragma :prag1 value1 :prag2 (get-value2))
Each key is a literal keyword giving the name of a pragma. Each value is an
arbitrary form, which is evaluated as ordinary Hy code but at compile-time.
Generally, the effect of each pragma is locally scoped to its containing
function, class, or comprehension form (other than ``for``), if there is one.
The exception is pragmata that affect the reader (marked "(reader)" below),
in which case the current reader is affected, so as with a reader macro, you
generally need to put the pragma *before* the top-level form in which you
want to use it.
These pragmata are currently implemented:
- ``:hy``: Set this to a string giving a Hy version number or prefix thereof,
such as "1.1.0" or "1", to raise a compile-time error if the currently
executing version of Hy isn't at least this new. If you're writing a
package, you should still declare the required version of Hy in ``setup.py``
or ``pyproject.toml`` or whatever, because ``pip`` won't look for ``(pragma
:hy …)`` calls. In the future, this pragma may also switch on features of Hy
that were introduced in or before the given version.
.. _warn-on-core-shadow:
- ``:warn-on-core-shadow``: If true (the default), :hy:func:`defmacro` and
:hy:func:`require` will raise a warning at compile-time if you define a macro
with the same name as a core macro. Shadowing a core macro in this fashion is
dangerous, because other macros may call your new macro when they meant to
refer to the core macro.
.. _bracketed-templates:
- ``:bracketed-templates`` (reader; requires Hy 1.3): If true (default:
false), :ref:`bracket strings ` using the delimiter "t" or
any delimiter starting with "t-" are parsed as :ref:`template strings
<syntax-tstrings>`.
Quoting.. hy:macro:: (quote [model])
Return the given :ref:model <models> without evaluating it. Or to be more pedantic, quote complies to code that produces and returns the model it was originally called on. Thus quote serves as syntactic sugar for model constructors::
(quote a)
; Equivalent to: (hy.models.Symbol "a")
(quote (+ 1 1))
; Equivalent to: (hy.models.Expression [
; (hy.models.Symbol "+")
; (hy.models.Integer 1)
; (hy.models.Integer 1)]) quote itself is conveniently :ref:abbreviated <more-sugar> as the single-quote character ', which needs no parentheses, allowing one to instead write::
'a
'(+ 1 1)See also:
- :hy:func:`quasiquote` to substitute values into a quoted form
- :hy:func:`hy.eval` to evaluate models as code
- :hy:func:`hy.repr` to stringify models into Hy source text that uses ``'``.. hy:macro:: (quasiquote [model])
.. hy:macro:: (unquote [model])
.. hy:macro:: (unquote-splice [model])
quasiquote is like :hy:func:quote except that it treats the model as a template, in which certain special :ref:expressions <expressions> indicate that some code should be evaluated and its value substituted there. The idea is similar to C's sprintf or Python's various string-formatting constructs. For example::
(setv x 2)
(quasiquote (+ 1 (unquote x))) ; => '(+ 1 2) unquote indicates code to be evaluated, so x becomes 2 and the 2 gets inserted in the parent model. quasiquote can be :ref:abbreviated <more-sugar> as a backtick (`), with no parentheses, and likewise unquote can be abbreviated as a tilde (~), so one can instead write simply ::
`(+ 1 ~x) (In the bulk of Lisp tradition, unquotation is written ,. Hy goes with Clojure's choice of ~, which has the advantage of being more visible in most programming fonts.)
Quasiquotation is convenient for writing macros::
(defmacro set-foo [value]
`(setv foo ~value))
(set-foo (+ 1 2 3))
(print foo) ; => 6 Another kind of unquotation operator, unquote-splice, abbreviated ~@, is analogous to unpack-iterable in that it splices an iterable object into the sequence of the parent :ref:sequential model <hysequence>. Compare the effects of unquote to unquote-splice::
(setv X [1 2 3])
(hy.repr `[a b ~X c d ~@X e f])
; => '[a b [1 2 3] c d 1 2 3 e f] If unquote-splice is given any sort of false value (such as None), it's treated as an empty list. To be precise, ~@x splices in the result of (or x []).
Note that while a symbol name can begin with @ in Hy, ~@ takes precedence in the parser, so if you want to unquote the symbol @foo with ~, you must use whitespace to separate ~ and @, as in ~ @foo.
Assignment, mutation, and annotation
.. hy:macro:: (setv [#* args])
``setv`` compiles to an :ref:`assignment statement ` (see :hy:func:`setx` for assignment expressions), which sets the value of a variable or some other assignable expression. It requires an even number of arguments, and always returns ``None``. The most common case is two arguments, where the first is a symbol::
(setv websites 103)
(print websites) ; => 103
Additional pairs of arguments are equivalent to several two-argument ``setv`` calls, in the given order. Thus, the semantics are like Common Lisp's ``setf`` rather than ``psetf``. ::
(setv x 1 y x x 2)
(print x y) ; => 2 1
All the same kinds of complex assignment targets are allowed as in Python. So, you can use list assignment to assign in parallel. (As in Python, tuple and list syntax are equivalent for this purpose; Hy differs from Python merely in that its list syntax is shorter than its tuple syntax.) ::
(setv [x y] [y x]) ; Swaps the values of `x` and `y`
Unpacking assignment looks like this (see :hy:func:`unpack-iterable`)::
(setv [letter1 letter2 #* others] "abcdefg")
(print letter1 letter2 (hy.repr others))
; => a b ["c" "d" "e" "f" "g"]
Finally, as of Hy 1.2, you can precede an assignment pair with the keyword ``:chain`` to assign the same value multiple times to each of several targets. This construct compiles to a chained assignment in Python. ::
(setv :chain [x y z] 0)
(print x y z)
; => 0 0 0
See :hy:func:`let` to simulate more traditionally Lispy block-level scoping.
.. hy:macro:: (setx [target value])
``setx`` compiles to an assignment expression (:pep:`572`). Thus, unlike :hy:func:`setv`, it returns the assigned value. It takes exactly two arguments, and the target must be a bare symbol. ::
(when (> (setx x (+ 1 2)) 0)
(print x "is greater than 0"))
; => 3 is greater than 0
.. hy:macro:: (let [bindings #* body])
``let`` is a macro for simulating traditional block scoping as seen in other
Lisps. Since it coexists with ordinary Python scoping, its consequences can
be complex, so it's wise to get a solid understanding of Python scoping
before you use it. Beginners to Python should note particularly that
:hy:func:`setv` inside a function or class typically creates a local
variable, so ``let`` isn't required for local variables or closures as it is
in many other Lisps.
That disclaimer aside, ``let`` creates local variables with lexically scoped
names. The macro takes a list of binding pairs followed by a ``body`` which
gets executed. A let-bound name ceases to refer to that local outside the
``let`` form, but arguments in nested functions, and bindings in nested
``let`` forms, can shadow these names. ::
(let [x 5 y 6] ; Create `x` and `y`
(print x y) ; => 5 6
(let [x 7] ; Create a variable that shadows the earlier `x`
(print x y)) ; => 7 6
(print x y)) ; => 5 6
The left-hand item of a binding pair is typically a plain symbol, but it can also use extended iterable unpacking (:pep:`3132`)::
(let [[head #* tail] #(0 1 2)]
[head tail]) ; => [0 [1 2]]
Basic assignments, as with :hy:func:`setv` or ``+=``, will update the local
variable named by a let binding when they assign to a let-bound name.
But assignments via :hy:func:`import` are always hoisted to normal Python
scope, and likewise, :hy:func:`defn` or :hy:func:`defclass` will assign the
function or class in the Python scope, even if it shares the name of
a let binding. To avoid this hoisting, use
:func:`importlib.import_module`, :hy:func:`fn`, or :class:`type` (or whatever
metaclass) instead.
If :hy:func:`lfor`, :hy:func:`sfor`, :hy:func:`dfor`, or :hy:func:`gfor` (but not :hy:func:`for`) is in
the body of a ``let``, assignments in iteration clauses and ``:setv``
clauses will create a new variable in the comprehenion form's own
scope, without touching any outer let-bound variable of the same
name.
Like the ``let*`` of many other Lisps, ``let`` executes the variable
assignments one-by-one, in the order written::
(let [x 5
y (+ x 1)]
(print x y)) ; => 5 6
(let [x 1
x (fn [] x)]
(x)) ; => 1
Note that let-bound variables continue to exist in the surrounding
Python scope. As such, let-bound objects may not be eligible for
garbage collection as soon as the ``let`` ends. To ensure there are
no references to let-bound objects as soon as possible, use
``del`` at the end of the ``let``, or wrap the ``let`` in a function.
.. hy:macro:: (global [#* syms])
``global`` compiles to a :py:keyword:`global` statement, which declares one
or more names as referring to global (i.e., module-level) variables. The
arguments are symbols; with no arguments, ``global`` has no effect. The
return value is always ``None``. ::
(setv a 1 b 10)
(print a b) ; => 1 10
(defn f []
(global a)
(setv a 2 b 20))
(f)
(print a b) ; => 2 10
.. hy:macro:: (nonlocal [#* syms])
Similar to :hy:func:`global`, but names can be declared in any enclosing
scope. ``nonlocal`` compiles to a :py:keyword:`global` statement for any
names originally defined in the global scope, and a :py:keyword:`nonlocal`
statement for all other names. ::
(setv a 1 b 1)
(defn f []
(setv c 10 d 10)
(defn g []
(nonlocal a c)
(setv a 2 b 2
c 20 d 20))
(print a b c d) ; => 1 1 10 10
(g)
(print a b c d)) ; => 2 1 20 10
(f)
.. hy:macro:: (del [#* args])
``del`` compiles to a :py:keyword:`del` statement, which deletes variables
or other assignable expressions. It always returns ``None``. ::
(del foo (get mydict "mykey") myobj.myattr)
.. hy:macro:: (annotate [value type])
``annotate`` and its shorthand form ``#^`` are used to denote annotations,
including type hints, in three different contexts:
- Standalone variable annotations (:pep:`526`)
- Variable annotations in a :hy:func:`setv` call
- Function-parameter annotations (:pep:`3107`)
The difference between ``annotate`` and ``#^`` is that ``annotate`` requires
parentheses and takes the name to be annotated first (like Python), whereas
``#^`` doesn't require parentheses (it only applies to the next two forms)
and takes the name second::
(setv (annotate x int) 1)
(setv #^ int x 1)
The order difference is not merely visual: ``#^`` actually evaluates the
type first.
Here are examples with ``#^`` for all the places you can use annotations::
; Annotate the variable `x` as an `int` (equivalent to `x: int`).
#^ int x
; You can annotate with expressions (equivalent to `y: f(x)`).
#^(f x) y
; Annotations with an assignment: each annotation `(int, str)`
; covers the term that immediately follows.
; Equivalent to `x: int = 1; y = 2; z: str = 3`
(setv #^ int x 1 y 2 #^ str z 3)
; Annotate `a` as an `int`, `c` as an `int`, and `b` as a `str`.
; Equivalent to `def func(a: int, b: str = None, c: int = 1): ...`
(defn func [#^ int a #^ str [b None] #^ int [c 1]] ...)
; Function return annotations come before the function name (if
; it exists).
(defn #^ int add1 [#^ int x] (+ x 1))
(fn #^ int [#^ int y] (+ y 2))
For annotating items with generic types, the :hy:func:`of <hyrule.of>`
macro will likely be of use.
An issue with type annotations is that, as of this writing, we know of no Python type-checker that can work with :py:mod:`ast` objects or bytecode files. They all need Python source text. So you'll have to translate your Hy with :ref:`hy2py` in order to actually check the types.
.. hy:macro:: (deftype [args])
``deftype`` compiles to a :py:keyword:`type` statement, which defines a
type alias. It requires Python 3.12. Its arguments optionally begin with
``:tp`` and a list of type parameters (as in :hy:func:`defn`), then specify
the name for the new alias and its value. ::
(deftype IntOrStr (| int str))
(deftype :tp [T] ListOrSet (| (get list T) (get set T)))
Subsetting
~~~~~~~~~~~~
.. _dot:
.. hy:data:: .
The dot macro ``.`` compiles to one or more :ref:`attribute references
`, which select an attribute of an object. The
first argument, which is required, can be an arbitrary form. With no further
arguments, ``.`` is a no-op. Additional symbol arguments are understood as a
chain of attributes, so ``(. foo bar)`` compiles to ``foo.bar``, and ``(. a b
c d)`` compiles to ``a.b.c.d``.
As a convenience, ``.`` supports two other kinds of arguments in place of a
plain attribute. A parenthesized expression is understood as a method call:
``(. foo (bar a b))`` compiles to ``foo.bar(a, b)``. A bracketed form is
understood as a subscript: ``(. foo ["bar"])`` compiles to ``foo["bar"]``.
All these options can be mixed and matched in a single ``.`` call, so ::
(. a (b 1 2) c [d] [(e 3 4)])
compiles to
.. code-block:: python
a.b(1, 2).c[d][e(3, 4)]
:ref:`Dotted identifiers <dotted-identifiers>` provide syntactic sugar for
common uses of this macro. In particular, syntax like ``foo.bar`` ends up
meaning the same thing in Hy as in Python. Also, :hy:func:`get
<hy.pyops.get>` is another way to subscript in Hy.
.. hy:macro:: (unpack-iterable [form])
.. hy:macro:: (unpack-mapping [form])
(Also known as the splat operator, star operator, argument expansion, argument
explosion, argument gathering, and varargs, among others...)
``unpack-iterable`` and ``unpack-mapping`` allow an iterable or mapping
object (respectively) to provide positional or keywords arguments
(respectively) to a function.
::
=> (defn f [a b c d] [a b c d])
=> (f (unpack-iterable [1 2]) (unpack-mapping {"c" 3 "d" 4}))
[1 2 3 4]
``unpack-iterable`` is usually written with the shorthand ``#*``, and
``unpack-mapping`` with ``#**``.
::
=> (f #* [1 2] #** {"c" 3 "d" 4})
[1 2 3 4]
Unpacking is allowed in a variety of contexts, and you can unpack
more than once in one expression (:pep:`3132`, :pep:`448`).
::
=> (setv [a #* b c] [1 2 3 4 5])
=> [a b c]
[1 [2 3 4] 5]
=> [#* [1 2] #* [3 4]]
[1 2 3 4]
=> {#** {1 2} #** {3 4}}
{1 2 3 4}
=> (f #* [1] #* [2] #** {"c" 3} #** {"d" 4})
[1 2 3 4]
Conditionals and basic loops
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. hy:macro:: (if [test true-value false-value])
``if`` compiles to an :py:keyword:`if` expression (or compound ``if`` statement). The form ``test`` is evaluated and categorized as true or false according to :py:class:`bool`. If the result is true, ``true-value`` is evaluated and returned. Othewise, ``false-value`` is evaluated and returned.
::
(if (has-money-left account)
(print "Let's go shopping!")
(print "Back to work."))
See also:
- :hy:func:`do`, to execute several forms as part of any of ``if``'s three arguments.
- :hy:func:`when <hy.core.macros.when>`, for shorthand for ``(if condition (do …) None)``.
- :hy:func:`cond <hy.core.macros.cond>`, for shorthand for nested ``if`` forms.
.. hy:automacro:: hy.core.macros.when
.. hy:automacro:: hy.core.macros.cond
.. hy:macro:: (while [condition #* body])
``while`` compiles to a :py:keyword:`while` statement, which executes some
code as long as a condition is met. The first argument to ``while`` is the
condition, and any remaining forms constitute the body. It always returns
``None``. ::
(while True
(print "Hello world!"))
The last form of a ``while`` loop can be an ``else`` clause, which is
executed after the loop terminates, unless it exited abnormally (e.g., with
``break``). So, ::
(setv x 2)
(while x
(print "In body")
(-= x 1)
(else
(print "In else")))
prints ::
In body
In body
In else
If you put a ``break`` or ``continue`` form in the condition of a ``while``
loop, it will apply to the very same loop rather than an outer loop, even if
execution is yet to ever reach the loop body. (Hy compiles a ``while`` loop
with statements in its condition by rewriting it so that the condition is
actually in the body.) So, ::
(for [x [1]]
(print "In outer loop")
(while
(do
(print "In condition")
(break)
(print "This won't print.")
True)
(print "This won't print, either."))
(print "At end of outer loop"))
prints ::
In outer loop
In condition
At end of outer loop
.. hy:macro:: (break)
``break`` compiles to a :py:keyword:`break` statement, which terminates the
enclosing loop. The following example has an infinite ``while`` loop that
ends when the user enters "k"::
(while True
(if (= (input "> ") "k")
(break)
(print "Try again")))
In a loop with multiple iteration clauses, such as ``(for [x xs y ys] …)``,
``break`` only breaks out of the innermost iteration, not the whole form. To
jump out of the whole form, enclose it in a :hy:func:`block
<hyrule.block>` and use ``block-ret`` instead of ``break``. In
the case of :hy:func:`for`, but not :hy:func:`lfor` and the other
comprehension forms, you may also enclose it in a function and use
:hy:func:`return`.
.. hy:macro:: (continue)
``continue`` compiles to a :py:keyword:`continue` statement, which returns
execution to the start of a loop. In the following example, ``(.append
output x)`` is executed on each iteration, whereas ``(.append evens x)`` is
only executed for even numbers.
::
(setv output [] evens [])
(for [x (range 10)]
(.append output x)
(when (% x 2)
(continue))
(.append evens x))
In a loop with multiple iteration clauses, such as ``(for [x xs y ys] …)``,
``continue`` applies to the innermost iteration, not the whole form. To jump
to the next step of an outer iteration, try rewriting your loop as multiple
nested loops and interposing a :hy:func:`block <hyrule.block>`, as in
``(for [x xs] (block (for [y ys] …)))``. You can then use ``block-ret`` in
place of ``continue``.
Comprehensions
~~~~~~~~~~~~~~
.. hy:macro:: (for [#* args])
``for`` compiles to one or more :py:keyword:`for` statements, which execute
code repeatedly for each element of an iterable object. The return values of
the forms are discarded and the ``for`` form returns ``None``. ::
(for [x [1 2 3]]
(print "iterating")
(print x))
; Output: iterating 1 iterating 2 iterating 3
The first argument of ``for``, in square brackets, specifies how to loop. A
simple and common case is ``[variable values]``, where ``values`` is an
iterable object (such as a list) and ``variable`` is a symbol specifiying
the name for each element. Subsequent arguments to ``for`` are body forms to
be evaluated for each iteration of the loop.
More generally, the first argument of ``for`` allows the same types of
clauses as :hy:func:`lfor`::
(for [x [1 2 3] :if (!= x 2) y [7 8]]
(print x y))
; Output: 1 7 1 8 3 7 3 8
In particular, you can use an ``:async`` clause to get the equivalent of
Python's :py:keyword:`async for`::
(import asyncio)
(defn :async numbers []
(yield 1)
(yield 2))
(asyncio.run ((fn :async []
(for [:async x (numbers)]
(print x)))))
The last argument of ``for`` can be an ``(else …)`` form. This form is
executed after the last iteration of the ``for``\'s outermost iteration
clause, but only if that outermost loop terminates normally. If it's jumped
out of with e.g. :hy:func:`break`, the ``else`` is ignored. ::
(for [x [1 2 3]]
(print x)
(when (= x 2)
(break))
(else (print "loop finished")))
.. hy:macro:: (lfor [#* args])
The comprehension forms ``lfor``, :hy:func:`sfor`, :hy:func:`dfor`, :hy:func:`gfor`, and :hy:func:`for`
are used to produce various kinds of loops, including Python-style
:ref:`comprehensions <py:comprehensions>`. ``lfor`` in particular
can create a list comprehension. A simple use of ``lfor`` is::
(lfor x (range 5) (* 2 x)) ; => [0 2 4 6 8]
``x`` is the name of a new variable, which is bound to each element of
``(range 5)``. Each such element in turn is used to evaluate the value
form ``(* 2 x)``, and the results are accumulated into a list.
Here's a more complex example::
(lfor
x (range 3)
y (range 3)
:if (!= x y)
:setv total (+ x y)
[x y total])
; => [[0 1 1] [0 2 2] [1 0 1] [1 2 3] [2 0 2] [2 1 3]]
When there are several iteration clauses (here, the pairs of forms ``x
(range 3)`` and ``y (range 3)``), the result works like a nested loop or
Cartesian product: all combinations are considered in lexicographic
order.
The general form of ``lfor`` is::
(lfor CLAUSES VALUE)
where the ``VALUE`` is an arbitrary form that is evaluated to produce
each element of the result list, and ``CLAUSES`` is any number of
clauses. There are several types of clauses:
- Iteration clauses, which look like ``LVALUE ITERABLE``. The ``LVALUE``
is usually just a symbol, but could be something more complicated,
like ``[x y]``.
- ``:async LVALUE ITERABLE``, which is an asynchronous form of
iteration clause per Python's :py:keyword:`async for`.
- ``:do FORM``, which simply evaluates the ``FORM``. If you use
``(continue)`` or ``(break)`` here, it will apply to the innermost
iteration clause before the ``:do``.
- ``:setv LVALUE RVALUE``, which is equivalent to ``:do (setv LVALUE
RVALUE)``.
- ``:if CONDITION``, which is equivalent to ``:do (when (not CONDITION)
(continue))``.
As of Hy 1.3, ``VALUE`` may be an :hy:func:`unpack-iterable` form,
such as ``#* ITERABLE``, in which case the elements of ``ITERABLE``
will be returned instead. This corresponds to a new feature in Python
3.15 (:pep:`798`), but Hy supports it on all Python versions.
For ``lfor``, ``sfor``, ``gfor``, and ``dfor``, variables defined by
an iteration clause or ``:setv`` are not visible outside the form.
However, variables defined within the body, as with a ``setx``
expression, will be visible outside the form.
In ``for``, by contrast, iteration and ``:setv`` clauses share the
caller's scope and are visible outside the form.
.. hy:macro:: (dfor [#* args])
``dfor`` creates a :ref:`dictionary comprehension <py:dict>`. Its syntax
is the same as that of :hy:func:`lfor` except that it takes two trailing
arguments. The first is a form producing the key of each dictionary
element, and the second produces the value. Thus::
(dfor x (range 5) x (* x 10))
; => {0 0 1 10 2 20 3 30 4 40}
Alternatively, as of Hy 1.3, you may use an :hy:func:`unpack-mapping` form
as a single final argument to return all the items of the unpacked
mapping. ::
(dfor x [{1 10 2 20} {3 30 4 40}] #** x)
; => {1 10 2 20 3 30 4 40}
.. hy:macro:: (gfor [#* args])
``gfor`` creates a :ref:`generator expression <py:genexpr>`. Its syntax
is the same as that of :hy:func:`lfor`. The difference is that ``gfor`` returns
an iterator, which evaluates and yields values one at a time::
(import itertools [count take-while])
(setv accum [])
(list (take-while
(fn [x] (< x 5))
(gfor x (count) :do (.append accum x) x)))
; => [0 1 2 3 4]
accum
; => [0 1 2 3 4 5]
.. hy:macro:: (sfor [#* args])
``sfor`` creates a :ref:`set comprehension <py:set>`. ``(sfor CLAUSES VALUE)`` is
equivalent to ``(set (lfor CLAUSES VALUE))``. See :hy:func:`lfor`.
Context managers and pattern-matching.. hy:macro:: (with [managers #* body])
with compiles to a :py:keyword:with or an :py:keyword:async with
statement, which wraps some code with one or more :ref:context managers <py:context-managers>. The first argument is a bracketed list of context
managers, and the remaining arguments are body forms.
The manager list can't be empty. If it has only one item, that item is
evaluated to obtain the context manager to use. If it has two, the first
argument (a symbol) is bound to the result of the second. Thus, (with [(f)] …) compiles to with f(): … and (with [x (f)] …) compiles to
with f() as x: …. ::
(with [o (open "file.txt" "rt")]
(print (.read o))) If the manager list has more than two items, they're understood as
variable-manager pairs; thus ::
(with [v1 e1 v2 e2 v3 e3] ...)compiles to
.. code-block:: python
with e1 as v1, e2 as v2, e3 as v3: ... The symbol _ is interpreted specially as a variable name in the manager
list: instead of binding the context manager to the variable _ (as
Python's with e1 as _: …), with will leave it anonymous (as Python's
with e1: …).
Finally, any variable-manager pair may be preceded by the keyword
:async to use an asynchronous context manager::
(with [:async v1 e1] …) with returns the value of its last form, unless it suppresses an
exception (because the context manager's __exit__ method returned true),
in which case it returns None. So, the first example could also be
written ::
(print (with [o (open "file.txt" "rt")] (.read o))).. hy:macro:: (match [subject #* cases])
match compiles to a :ref:match statement <py:match>. It
requires Python 3.10 or later. The first argument should be the subject,
and any remaining arguments should be pairs of patterns and results. The
match form returns the value of the corresponding result, or
None if no case matched. ::
(match (+ 1 1)
1 "one"
2 "two"
3 "three")
; => "two" You can use :hy:func:do to build a complex result form. Patterns, as
in Python match statements, are interpreted specially and can't be
arbitrary forms. Use (| …) for OR patterns, PATTERN :as NAME for
AS patterns, and syntax like the usual Hy syntax for literal, capture,
value, sequence, mapping, and class patterns. Guards are specified
with :if FORM. Here's a more complex example::
(match #(100 200)
[100 300] "Case 1"
[100 200] :if flag "Case 2"
[900 y] f"Case 3, y: {y}"
[100 (| 100 200) :as y] f"Case 4, y: {y}"
_ "Case 5, I match anything!") This will match case 2 if flag is true and case 4 otherwise.
match can also match against class instances by keyword (or
positionally if its __match_args__ attribute is defined; see :pep:636)::
(import dataclasses [dataclass])
(defclass [dataclass] Point []
#^ int x
#^ int y)
(match (Point 1 2)
(Point 1 x) :if (= (% x 2) 0) x) ; => 2 It's worth emphasizing that match is a pattern-matching construct
rather than a generic switch <https://en.wikipedia.org/wiki/Switch_statement>_ construct, and
retains all of Python's limitations on match patterns. For example, you
can't match against the value of a variable. For more flexible branching
constructs, see Hyrule's :hy:func:branch <hyrule.branch> and
:hy:func:case <hyrule.case>, or simply use :hy:func:cond <hy.core.macros.cond>.
Exception-handling
.. hy:macro:: (raise [exception :from other])
``raise`` compiles to a :py:keyword:`raise` statement, which throws an
exception. With no arguments, the current exception is reraised. With one
argument, an exception, that exception is raised. ::
(try
(raise KeyError)
(except [KeyError]
(print "gottem")))
``raise`` supports one other syntax, ``(raise EXCEPTION_1 :from
EXCEPTION_2)``, which compiles to ``raise EXCEPTION_1 from EXCEPTION_2``.
.. hy:macro:: (try [#* body])
``try`` compiles to a :py:keyword:`try` statement, which can catch
exceptions and run cleanup actions. It begins with any number of body forms.
Then follows any number of ``except`` or ``except*`` (:pep:`654`) forms,
which are expressions that begin with the symbol in question, followed by a
list of exception types, followed by more body forms. Finally there are an
optional ``else`` form and an optional ``finally`` form, which again are
expressions that begin with the symbol in question and then comprise body
forms. Note that ``except*`` requires Python 3.11, and ``except*`` and
``except`` may not both be used in the same ``try``.
Here's an example of several of the allowed kinds of child forms::
(try
(error-prone-function)
(another-error-prone-function)
(except [ZeroDivisionError]
(print "Division by zero"))
(except [[IndexError KeyboardInterrupt]]
(print "Index error or Ctrl-C"))
(except [e ValueError]
(print "ValueError:" (repr e)))
(except [e [TabError PermissionError ReferenceError]]
(print "Some sort of error:" (repr e)))
(else
(print "No errors"))
(finally
(print "All done")))
Exception lists can be in any of several formats:
- ``[]`` to catch any subtype of ``Exception``, like Python's ``except:``
- ``[ETYPE]`` to catch only the single type ``ETYPE``, like Python's
``except ETYPE:``
- ``[[ETYPE1 ETYPE2 …]]`` to catch any of the named types, like Python's
``except ETYPE1, ETYPE2, …:``
- ``[VAR ETYPE]`` to catch ``ETYPE`` and bind it to ``VAR``, like Python's
``except ETYPE as VAR:``
- ``[VAR [ETYPE1 ETYPE2 …]]`` to catch any of the named types and bind it to
``VAR``, like Python's ``except ETYPE1, ETYPE2, … as VAR:``
- ``[[]]`` or ``[VAR []]`` to catch no exceptions, like Python's
``except ():``.
The return value of ``try`` is the last form evaluated among the main body,
``except`` forms, ``except*`` forms, and ``else``.
Functions
~~~~~~~~~
.. hy:macro:: (defn [name #* args])
``defn`` compiles to a :ref:`function definition ` (or possibly
to an assignment of a :ref:`lambda expression `). It always
returns ``None``. It requires two arguments: a name (given as a symbol; see
:hy:func:`fn` for anonymous functions) and a "lambda list", or list of
parameters (also given as symbols). Any further arguments constitute the
body of the function::
(defn name [params] bodyform1 bodyform2…)
An empty body is implicitly ``(return None)``. If there are at least two body
forms, and the first of them is a string literal, this string becomes the
:term:`py:docstring` of the function. The final body form is implicitly
returned; thus, ``(defn f [] 5)`` is equivalent to ``(defn f [] (return
5))``. There is one exception: due to Python limitations, no implicit return
is added if the function is an asynchronous generator (i.e., defined with
``(defn :async …)`` or ``(fn :async …)`` and containing at least one
:hy:func:`yield`).
``defn`` accepts a few more optional arguments: a literal keyword ``:async``
(to create a coroutine like Python's :keyword:`async def`), a
bracketed list of :term:`decorators `, a list of type
parameters (see below), and an annotation (see :hy:func:`annotate`) for the
return value. These are placed before the function name (in that order, if
several are present)::
(defn :async [decorator1 decorator2] :tp [T1 T2] #^ annotation name [params] …)
``defn`` lambda lists support all the same features as Python parameter
lists and hence are complex in their full generality. The simplest case is a
(possibly empty) list of symbols, indicating that all parameters are
required, and can be set by position, as in ``(f value)``, or by name, as in
``(f :argument value)``. To set a default value for a parameter, replace the
parameter with the bracketed list ``[pname value]``, where ``pname`` is the
parameter name as a symbol and ``value`` is an arbitrary form. Beware that,
per Python, ``value`` is evaluated when the function is defined, not when
it's called, and if the resulting object is mutated, all calls will see the
changes.
Further special lambda-list syntax includes:
``/``
If the symbol ``/`` is given in place of a parameter, it means that all
the preceding parameters can only be set positionally.
``*``
If the symbol ``*`` is given in place of a parameter, it means that all
the following parameters can only be set by name.
``#* args``
If the parameter list contains ``#* args`` or ``(unpack-iterable
args)``, then ``args`` is set to a tuple containing all otherwise
unmatched positional arguments. The name ``args`` is merely cherished
Python tradition; you can use any symbol.
``#** kwargs``
``#** kwargs`` (a.k.a. ``(unpack-mapping kwargs)``) is like ``#*
args``, but collects unmatched keyword arguments into a dictionary.
Each of these special constructs is allowed only once, and has the same
restrictions as in Python; e.g., ``#* args`` must precede ``#** kwargs`` if
both are present. Here's an example with a complex lambda list::
(defn f [a / b [c 3] * d e #** kwargs]
[a b c d e kwargs])
(print (hy.repr (f 1 2 :d 4 :e 5 :f 6)))
; => [1 2 3 4 5 {"f" 6}]
Type parameters require Python 3.12, and have the semantics specified by
:pep:`695`. The keyword ``:tp`` introduces the list of type parameters. Each
item of the list is a symbol, an annotated symbol (such as ``#^ int T``), or
an unpacked symbol (such as ``#* T`` or ``#** T``). As in Python, a single
parameter can't be both annotated and unpacked.
.. hy:macro:: (fn [args])
As :hy:func:`defn`, but no name for the new function is required (or
allowed), and the newly created function object is returned. Decorators and
type parameters aren't allowed, either. However, the function body is
understood identically to that of :hy:func:`defn`, without any of the
restrictions of Python's :py:keyword:`lambda`. ``:async`` is also allowed.
.. hy:macro:: (return [object])
``return`` compiles to a :py:keyword:`return` statement. It exits the
current function, returning its argument if provided with one, or
``None`` if not. ::
(defn f [x]
(for [n (range 10)]
(when (> n x)
(return n))))
(f 3.9) ; => 4
Note that in Hy, ``return`` is necessary much less often than in Python.
The last form of a function is returned automatically, so an
explicit ``return`` is only necessary to exit a function early. To get
Python's behavior of returning ``None`` when execution reaches the end of a
function, just put ``None`` there yourself::
(defn f []
(setv d (dict :a 1 :b 2))
(.pop d "b")
None)
(print (f)) ; Prints "None", not "2"
.. hy:macro:: (yield [arg1 arg2])
``yield`` compiles to a :ref:`yield expression `, which
returns a value as a generator. For a plain yield, provide one argument,
the value to yield, or omit it to yield ``None``. ::
(defn naysayer []
(while True
(yield "nope")))
(list (zip "abc" (naysayer)))
; => [#("a" "nope") #("b" "nope") #("c" "nope")]
For a yield-from expression, provide two arguments, where the first is the
literal keyword ``:from`` and the second is the subgenerator. ::
(defn myrange []
(setv r (range 10))
(while True
(yield :from r)))
(list (zip "abc" (myrange)))
; => [#("a" 0) #("b" 1) #("c" 2)]
.. hy:macro:: (await [obj])
``await`` creates an :ref:`await expression `. It takes exactly one
argument: the object to wait for. ::
(import asyncio)
(defn :async main []
(print "hello")
(await (asyncio.sleep 1))
(print "world"))
(asyncio.run (main))
Macros
~~~~~~~~~~~~
.. hy:macro:: (defmacro [name lambda-list #* body])
Define a macro, at both compile-time and run-time. The syntax is a subset
allowed of that by :hy:func:`defn`: no decorator or return-type annotations
are allowed, and the only types of parameter allowed are ``symbol``,
``[symbol default-value]``, ``/``, and ``#* args``. See :ref:`macros` for
details and examples.
.. hy:automacro:: hy.core.macros.defreader
.. hy:automacro:: hy.core.macros.get-macro
.. hy:automacro:: hy.core.macros.local-macros
Classes
~~~~~~~~~~~~
.. hy:macro:: (defclass [arg1 #* args])
``defclass`` compiles to a :py:keyword:`class` statement, which creates a
new class. It always returns ``None``. Only one argument, specifying the
name of the new class as a symbol, is required. A list of :term:`decorators
` (and type parameters, in the same way as for
:hy:func:`defn`) may be provided before the class name. After the name comes
a list of superclasses (use the empty list ``[]`` for the common case of no
superclasses) and any number of body forms, the first of which may be a
:term:`py:docstring`.
A simple class declaration and its uses might look like this::
(defclass MyClass []
"A simple example class."
(setv i 12345)
(defn f [self]
"hello world"))
(setv instance (MyClass))
(print instance.i) ; => 12345
(print (.f instance)) ; => hello world
A more complex declaration might look like this::
(defclass [decorator1 decorator2] :tp [T1 T2] MyClass [SuperClass1 SuperClass2]
"A class that does things at times."
(setv
attribute1 value1
attribute2 value2)
(defn method1 [self arg1 arg2]
…)
(defn method2 [self arg1 arg2]
…))
Modules
~~~~~~~~~~~~
.. hy:macro:: (import [#* forms])
``import`` compiles to an :py:keyword:`import` statement, which makes objects
in a different module available in the current module. It always returns
``None``. Hy's syntax for the various kinds of import looks like this::
;; Import each of these modules.
;; Python: import sys, os.path
(import sys os.path)
;; Import several names from a single module.
;; Python: from os.path import exists, isdir as is_dir, isfile
(import os.path [exists isdir :as is-dir isfile])
;; Import a module with an alias for the whole module.
;; Python: import sys as systest
(import sys :as systest)
;; Import all objects from a module into the current namespace.
;; Python: from sys import *
(import sys *)
;; You can list as many imports as you like of different types.
;; Python:
;; from tests.resources import kwtest, function_with_a_dash
;; from os.path import exists, isdir as is_dir, isfile as is_file
;; import sys as systest
;; from math import *
(import tests.resources [kwtest function-with-a-dash]
os.path [exists
isdir :as is-dir
isfile :as is-file]
sys :as systest
math *)
;; On Python 3.15 or later, the keyword `:lazy` may be used as
;; the first argument to enable lazy importing (PEP 810), which
;; applies to all modules in the form.
;; Python:
;; lazy import os, math
;; lazy from cmath import sqrt
(import :lazy
os
math
cmath [sqrt])
``__all__`` can be set to control what's imported by ``(import module-name
*)``, as in Python, but beware that all names in ``__all__`` must be
:ref:`mangled <mangling>`. The macro :hy:func:`export
<hy.core.macros.export>` is a handy way to set ``__all__`` in a Hy program.
.. hy:macro:: (require [#* args])
``require`` is a version of :hy:func:`import` for macros. It allows all the
same syntax as :hy:func:`import`, and brings the requested macros into the
current scope at compile-time as well as run-time. The following are all
equivalent ways to call a macro named ``foo`` in the module ``mymodule``::
(require mymodule)
(mymodule.foo 1)
(require mymodule :as M)
(M.foo 1)
(require mymodule [foo])
(foo 1)
(require mymodule *)
(foo 1)
(require mymodule [foo :as bar])
(bar 1)
There's a bit of a trick involved in syntax such as ``mymodule.foo``.
Namely, there is no object named ``mymodule``. Instead, ``(require
mymodule)`` assigns every macro ``foo`` in ``mymodule`` to the name
``(hy.mangle "mymodule.foo")`` in ``_hy_macros``.
Reader macros have a different namespace from regular macros, so they need
to be specified with the added syntax ``:readers […]``. You could require a
reader macro named ``spiff`` with the call ``(require mymodule :readers
[spiff])``, or star-require reader macros with ``(require mymodule :readers
*)``. For legibility, a regular-macros specification may analogously be
prefixed ``:macros``::
(require mymodule :macros [foo] :readers [spiff])
``require`` with reader macros is more limited than with regular macros. You
can't access reader macros with dotted names, and you can't rename them with
``:as``.
Note that ``(require mymodule :readers [spiff])`` doesn't imply ``(require
mymodule)``; that is, ``mymodule.foo`` won't be made available. If you want
that, use something like ::
(require mymodule
mymodule :readers [spiff])
To define which macros are collected by ``(require mymodule *)``, set the
variable ``_hy_export_macros`` (analogous to Python's ``__all__``) to a list
of :ref:`mangled <mangling>` macro names, which is accomplished most
conveniently with :hy:func:`export <hy.core.macros.export>`. The default
behavior is analogous to ``(import mymodule *)``: all macros are collected
other than those whose mangled names begin with an underscore (``_``),
.. hy:automacro:: hy.core.macros.export
Miscellany
~~~~~~~~~~~~
.. hy:macro:: (chainc [#* args])
``chainc`` creates a :ref:`comparison expression `. It isn't
required for unchained comparisons, which have only one comparison operator,
nor for chains of the same operator. For those cases, you can use the
comparison operators directly with Hy's usual prefix syntax, as in ``(= x 1)``
or ``(< 1 2 3)``. The use of ``chainc`` is to construct chains of
heterogeneous operators, such as ``x <= y < z``. It uses an infix syntax with
the general form ::
(chainc ARG OP ARG OP ARG…)
Hence, ``(chainc x <= y < z)`` is equivalent to ``(and (<= x y) (< y z))``,
including short-circuiting, except that ``y`` is only evaluated once.
Each ``ARG`` is an arbitrary form, which does not itself use infix syntax. Use
:hy:func:`py ` if you want fully Python-style operator syntax. You can
also nest ``chainc`` forms, although this is rarely useful. Each ``OP`` is a
literal comparison operator; other forms that resolve to a comparison operator
are not allowed.
At least two ``ARG``\ s and one ``OP`` are required, and every ``OP`` must be
followed by an ``ARG``.
As elsewhere in Hy, the equality operator is spelled ``=``, not ``==`` as in
Python.
.. hy:macro:: (assert [condition [label None]])
``assert`` compiles to an :py:keyword:`assert` statement, which checks
whether a condition is true. The first argument, specifying the condition to
check, is mandatory, whereas the second, which will be passed to
:py:class:`AssertionError`, is optional. The whole form is only evaluated
when :py:data:`__debug__` is true, and the second argument is only evaluated
when :py:data:`__debug__` is true and the condition fails. ``assert`` always
returns ``None``. ::
(assert (= 1 2) "one should equal two")
; AssertionError: one should equal two
Placeholder macros
~~~~~~~~~~~~~~~~~~
There are a few core macros that are unusual in that all they do, when
expanded, is crash, regardless of their arguments:
- ``else``
- ``except``
- ``except*``
- ``finally``
- ``unpack-mapping``
- ``unquote``
- ``unquote-splice``
The purpose of these macros is merely to reserve their names. Each
symbol is interpreted specially by one or more other core macros
(e.g., ``else`` in ``while``) and thus, in these contexts, any
definition of these names as a function or macro would be ignored. If
you really want to, you can override these names like any others, but
beware that, for example, trying to call your new ``else`` inside
``while`` may not work.
Hy
---
A few core functions, mostly related to the manipulation of Hy code, are
available through the module ``hy``.
.. hy:autofunction:: hy.read
.. hy:autofunction:: hy.read-many
.. hy:autofunction:: hy.eval
.. hy:autofunction:: hy.repr
.. hy:autofunction:: hy.repr-register
.. hy:autofunction:: hy.mangle
.. hy:autofunction:: hy.unmangle
.. hy:autofunction:: hy.macroexpand
.. hy:autofunction:: hy.macroexpand-1
.. hy:autofunction:: hy.gensym
.. hy:autofunction:: hy.as-model
.. hy:autoclass:: hy.I
.. hy:class:: (hy.R)
There is no actual object named ``hy.R``. Rather, this syntax is :ref:`recognized specially by the compiler <hy.R>` as a shorthand for requiring and calling a macro.
Readers
-------
Hy's reader (i.e., parser) classes are most interesting to the user in the
context of :ref:`reader macros <reader-macros>`.
.. autoclass:: hy.HyReader
:members: parse, parse_one_form, parse_forms_until, read_default, fill_pos
.. autoclass:: hy.Reader
:members:
.. autoexception:: hy.PrematureEndOfInput
.. _pyop:
Python operators
----------------
.. hy:automodule:: hy.pyops
:members:
---
### Cli (`docs/cli.rst`)
======================
Command-line interface
======================
Hy provides a handful of command-line programs for working with Hy code.
.. contents:: Contents
:local:
.. _hy-cli:
hy
--
``hy`` is a command-line interface for Hy that in general imitates the program
``python`` provided by CPython. For example, ``hy`` without arguments launches
the :ref:`REPL <repl>` if standard input is a TTY and runs the standard input
as a script otherwise, whereas ``hy foo.hy a b`` runs the Hy program
``foo.hy`` with ``a`` and ``b`` as command-line arguments. See ``hy --help``
for a complete list of options and :py:ref:`Python's documentation
` for many details. Here are some Hy-specific details:
.. cmdoption:: -m <module>
Much like Python's ``-m``, but the input module name will be :ref:`mangled
<mangling>`.
.. cmdoption:: --spy
Print equivalent Python code before executing each piece of Hy code in the
REPL::
=> (+ 1 2)
1 + 2
------------------------------
3
.. cmdoption:: --repl-output-fn
Set the :ref:`REPL output function <repl-output-function>`. This can be the
name of a Python builtin, most likely ``repr``, or a dotted name like
``foo.bar.baz``. In the latter case, Hy will attempt to import the named
object with code like ``(import foo.bar [baz])``.
.. _hy2py:
hy2py
-----
``hy2py`` is a program to convert Hy source code into Python source code. Use ``hy2py --help`` for usage instructions. It can take its input from standard input, or from a file or module name provided as a command-line argument. In the case of a module name, the current working directory should be the parent directory of that module, and the output parameter (``--output/-o``) is required. When the output parameter is provided, the output will be written into the given folder or file. Otherwise, the result is written to standard output.
.. warning::
``hy2py`` can execute arbitrary code (via macros, :hy:func:`eval-when-compile`, etc.). Don't give it untrusted input.
Hy has no built-in capacity to translate Python to Hy, but see `py2hy <https://github.com/hylang/py2hy>`__.
.. _hyc:
hyc
---
``hyc`` is a program to compile files of Hy code into Python bytecode. Use ``hyc --help`` for usage instructions. The generated bytecode files are named and placed according to the usual scheme of your Python executable, as indicated by :py:func:`importlib.util.cache_from_source`.
.. warning::
``hyc`` can execute arbitrary code (via macros, :hy:func:`eval-when-compile`, etc.). Don't give it untrusted input.
In practice, ``hyc`` is rarely useful, because Hy produces bytecode automatically. It exists mostly for historical reasons, and may be removed in a future major release of Hy.
---
### Coreteam (`docs/coreteam.rst`)
* `Peter Andreev <https://github.com/peaceamongworlds>`_
* `Kodi B. Arfer <https://github.com/Kodiologist>`_
* `Allie Jo Casey <http://github.com/allison-casey>`_
* `Sunjay Cauligi <https://github.com/scauligi>`_
* `Julien Danjou <https://github.com/jd>`_
* `Simon Gomizelj <https://github.com/vodik>`_
* `Ryan Gonzalez <https://github.com/refi64>`_
* `Morten Linderud <https://github.com/Foxboron>`_
* `Matthew Odendahl <https://github.com/gilch>`_
* `Paul Tagliamonte <https://github.com/paultag>`_
* `Brandon T. Willard <https://github.com/brandonwillard>`_
---
### Env Var (`docs/env_var.rst`)
=====================
Environment variables
=====================
Hy treats the following environment variables specially. Boolean environment
variables are interpreted as false when set to the empty string and true when
set to anything else.
.. envvar:: HYSTARTUP
(Default: nothing) Path to a file containing Hy source code to execute when
starting the REPL.
.. envvar:: HY_SHOW_INTERNAL_ERRORS
(Default: false) Whether to show some parts of tracebacks that point to
internal Hy code and won't be helpful to the typical Hy user.
.. envvar:: HY_HISTORY
(Default: ``~/.hy-history``) Path to which REPL input history will be saved.
.. envvar:: HY_MESSAGE_WHEN_COMPILING
(Default: false) Whether to print "Compiling FILENAME" to standard error
before compiling each file of Hy source code. This is helpful for debugging
whether files are being loaded from bytecode or re-compiled.
---
### Hacking (`docs/hacking.rst`)
.. _hacking:
===============
Developing Hy
===============
.. contents:: Contents
:local:
.. include:: ../CONTRIBUTING.rst
Core team
=========
Hy's core development team consists of the following people:
.. include:: coreteam.rst
---
### Index (`docs/index.rst`)
Contents
========
.. image:: _static/hy-logo-small.png
:alt: Hy
:align: left
:PyPI: https://pypi.python.org/pypi/hy
:Source: https://github.com/hylang/hy
:Discussions: https://github.com/hylang/hy/discussions
:Stack Overflow: `The [hy] tag <https://stackoverflow.com/questions/tagged/hy>`_
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.
.. Changes to the below paragraph should be mirrored on Hy's homepage
and the README.
To install the latest 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
whyhy
versioning
tutorial
syntax
semantics
macros
model_patterns
repl
env_var
cli
interop
api
hacking
---
### Interop (`docs/interop.rst`)
.. _interop:
=======================
Python interoperability
=======================
This chapter describes how to interact with Python code from Hy code and vice
versa.
.. contents:: Contents
:local:
Mangling
========
:ref:`Mangling <mangling>` allows variable names to be spelled differently in
Hy and Python. For example, Python's ``str.format_map`` can be written
``str.format-map`` in Hy, and a Hy function named ``valid?`` would be called
``hyx_valid_Xquestion_markX`` in Python. You can call :hy:func:`hy.mangle` and
:hy:func:`hy.unmangle` from either language.
Keyword mincing
---------------
Another kind of mangling may be necessary in Python to refer to variables with
the same name as reserved words. For example, while ``(setv break 13)`` is
legal Hy, ``import hy, my_hy_module; print(my_hy_module.break)`` is
syntactically invalid Python. String literals work, as in
``getattr(my_hy_module, "break")``, but to use what is syntactically a Python
identifier, you'll have to take advantage of Python's Unicode normalization
(via NFKC) and write something like ``my_hy_module.𝐛reak``. Here are all the
MATHEMATICAL BOLD SMALL letters (U+1D41A through U+1D433) for convenient
copying:
.. code-block:: text
𝐚𝐛𝐜𝐝𝐞𝐟𝐠𝐡𝐢𝐣𝐤𝐥𝐦𝐧𝐨𝐩𝐪𝐫𝐬𝐭𝐮𝐯𝐰𝐱𝐲𝐳
Libraries that expect Python
============================
There are various means by which Hy may interact poorly with a Python library because the library doesn't account for the possibility of Hy. For example,
when you run the program :ref:`hy-cli`, ``sys.executable`` will be set to
this program rather than the original Python binary. This is helpful more often
than not, but will lead to trouble if e.g. the library tries to call
:py:data:`sys.executable` with the ``-c`` option. In this case, you can try
setting :py:data:`sys.executable` back to ``hy.sys-executable``, which is a
saved copy of the original value. More generally, you can use :ref:`hy2py`, or you
can put a simple Python wrapper script like ``import hy, my_hy_program`` in
front of your code.
See `the wiki
<https://github.com/hylang/hy/wiki/Compatibility-tips>`_ for tips
on using specific packages.
Packaging a Hy library
======================
Generally, the same infrastructure used for Python packages, such as
``setup.py`` files and the `Python Package Index (PyPI) <https://pypi.org/>`__,
is applicable to Hy. Don't write the setup file itself in Hy, since you'll be
declaring your package's dependence on Hy there, likely in the
``install_requires`` argument of ``setup``. Similarly, at the top level of the
package, use ``__init__.py`` rather than ``__init__.hy``, and begin it with
``import hy`` to set up the import hooks for Hy. You can still import a Hy file
from there in order to write the real logic in Hy. If you want allow users to import or require from the top level of your module, as in ``from my_module import my_function`` or ``(require my-module [my-macro])``, use an ``__init__.py`` such as
.. code-block:: python
import hy
from my_module.hy_init import *
hy.eval(hy.read('(require my-module.hy-init :macros * :readers *)'))
If you want to compile your Hy code into Python bytecode at installation-time
(in case e.g. the code is being installed to a directory where the bytecode
can't be automatically written later, due to permissions issues), see Hy's own
``setup.py`` for an example.
For PyPI packages, use the trove classifier ``Programming Language :: Hy`` for
libraries meant to be useful for Hy specifically (e.g., a library that provides
Hy macros) or other projects that are about Hy somehow (e.g., an instructive
example Hy program). Don't use it for a package that just happens to be written
in Hy.
Using Python from Hy
====================
To use a Python module from Hy, just :hy:func:`import` it. In most cases, no
additional ceremony is required.
You can embed Python code directly into a Hy program with the macros
:hy:func:`py ` and :hy:func:`pys `, and you can use standard Python
tools like :func:`eval` or :func:`exec` to execute or manipulate Python code in
strings.
To translate Python code to Hy, see `py2hy <https://github.com/hylang/py2hy>`__.
.. _using-hy-from-python:
Using Hy from Python
====================
To use a Hy module from Python, you can just :py:keyword:`import` it, provided
that ``hy`` has already been imported first, whether in the current module or
in some earlier module executed by the current Python process. As mentioned
previously, you can put ``import hy`` in a package's ``__init__.py`` to make
this happen automatically.
You can use :ref:`hy2py` to convert a Hy program to Python. The output will
still import ``hy``, and thus require Hy to be installed in order to run; see
:ref:`implicit-names` for details and workarounds.
To execute Hy code from a string, use :hy:func:`hy.read-many` to convert it to
:ref:`models <models>` and :hy:func:`hy.eval` to evaluate it:
.. code-block:: python
>>> hy.eval(hy.read_many("(setv x 1) (+ x 1)"))
2
There is no Hy equivalent of :func:`exec` because :hy:func:`hy.eval` works
even when the input isn't equivalent to a single Python expression.
You can use :meth:`hy.REPL.run` to launch the Hy REPL from Python, as in
``hy.REPL(locals = {**globals(), **locals()}).run()``.
---
### Macros (`docs/macros.rst`)
.. _macros:
======
Macros
======
Macros, and the metaprogramming they enable, are one of the characteristic features of Lisp, and one of the main advantages Hy offers over vanilla Python. Much of the material covered in this chapter will be familiar to veterans of other Lisps, but there are also a lot of Hyly specific details.
.. contents:: Contents
:local:
What are macros for?
--------------------
The gist of `metaprogramming
<https://en.wikipedia.org/wiki/Metaprogramming>`_ is that it allows you to program the programming language itself (hence the word). You can create new control structures, like :ref:`do-while <do-while>`, or other kinds of new syntax, like a concise literal notation for your favorite data structure. You can also modify how existing syntax is understood within a region of code, as by making identifiers that start with a capital letter implicitly imported from a certain module. Finally, metaprogramming can improve performance in some cases by effectively inlining functions, or by computing something once at compile-time rather than several times at run-time. With a Lisp-like macro system, you can metaprogram in a slicker and less error-prone way than generating code as text with conventional string formatting, or with lexer-level macros like those provided by the C preprocessor.
Types of macros
---------------
Hy offers two types of macros: regular macros and reader macros.
**Regular macros**, typically defined with :hy:func:`defmacro`, are the kind Lispers usually mean when they talk about "macros". Regular macros are called like a function, with an :ref:`expression <expressions>` whose head is the macro name: for example, ``(foo a b)`` could call a macro named ``foo``. A regular macro is called at compile-time, after the entire top-level form in which it appears is parsed, and receives parsed :ref:`models <models>` as arguments. Regular macros come in :ref:`three varieties, which vary in scope <macro-namespaces>`.
**Reader macros**, typically defined with :hy:func:`defreader <hy.core.macros.defreader>`, are lower-level than regular macros. They're called with the hash sign ``#``; for example, ``#foo`` calls a reader macro named ``foo``. A reader macro is called at parse-time. It doesn't receive conventional arguments. Instead, it uses an implicitly available parser object to parse the subsequent source text. When it returns, the standard Hy parser picks up where it left off.
Related constructs
~~~~~~~~~~~~~~~~~~
There are three other constructs that perform compile-time processing much like macros, and hence are worth mentioning here.
- :hy:func:`do-mac` is essentially shorthand for defining and then immediately calling a regular macro with no arguments.
- :hy:func:`eval-when-compile` evaluates some code at compile-time, but contributes no code to the final program, like a macro that returns ``None`` in a context where the ``None`` doesn't do anything.
- :hy:func:`eval-and-compile` evaluates some code at compile-time, like :hy:func:`eval-when-compile`, but also leaves the same code to be re-evaluated at run-time.
When to use what
~~~~~~~~~~~~~~~~
The variety of options can be intimidating. In addition to all of Hy's features listed above, Python is a dynamic programming language that allows you to do a lot of things at run-time that other languages would blanch at. For example, you can dynamically define a new class by calling :class:`type`. So, watch out for cases where your first thought is to use a macro, but you don't actually need one.
When deciding what to use, a good rule of thumb is to use the least powerful option that suffices for the syntax, semantics, and performance that you want. So first, see if Python's dynamic features are enough. If they aren't, try a macro-like construct or a regular macro. If even those aren't enough, try a reader macro. Using the least powerful applicable option will help you avoid the :ref:`macro pitfalls described below <macro-pitfalls>`, as well as other headaches such as wanting to use a macro where a Python API needs a function. But for the sake of providing simpler examples, much of the below discussion will ignore this advice and consider example macros that could easily be written as functions.
The basics
----------
A regular macro can be defined with :hy:func:`defmacro` using a syntax similar to that of :hy:func:`defn`. Here's how you could define and call a trivial macro that takes no arguments and returns a constant::
(defmacro seventeen []
17)
(print (seventeen))
To see that ``seventeen`` is expanded at compile-time, run ``hy2py`` on this script and notice that it ends with ``print(17)`` rather than ``print(seventeen())``. If you insert a ``print`` call inside the macro definition, you'll also see that the print happens when the file is compiled, but not when it's rerun (so long as an up-to-date bytecode file exists).
A more useful macro returns code. You can construct a model the long way, like this::
(defmacro addition []
(hy.models.Expression [
(hy.models.Symbol "+")
(hy.models.Integer 1)
(hy.models.Integer 1)]))
or more concisely with :hy:func:`quote`, like this::
(defmacro addition []
'(+ 1 1))
You don't need to always return a model because the compiler calls :hy:func:`hy.as-model` on everything before trying to compile it. Thus, the ``17`` above works fine in place of ``(hy.models.Integer 17)``. But trying to compile something that ``hy.as-model`` chokes on, like a function object, is an error.
Arguments are always passed in as models. You can use quasiquotation (see :hy:func:`quasiquote`) to concisely define a model with partly literal and partly evaluated components::
(defmacro set-to-2 [variable]
`(setv ~variable 2))
(set-to-2 foobar)
(print foobar)
Macros don't understand keyword arguments like functions do. Rather, the :ref:`keyword objects <keywords>` themselves are passed in literally. This gives you flexibility in how to handle them. Thus, ``#** kwargs`` and ``*`` aren't allowed in the parameter list of a macro, although ``#* args`` and ``/`` are. See :hy:func:`hyrule.defmacro-kwargs` if you want to handle keyword arguments like a function.
On the inside, macros are functions, and obey the usual Python semantics for functions. For example, :hy:func:`setv` inside a macro will define or modify a variable local to the current macro call, and :hy:func:`return` ends macro execution and uses its argument as the expansion.
Macros from other modules can be brought into the current scope with :hy:func:`require`.
.. _macro-pitfalls:
Pitfalls
--------
Macros are powerful, but with great power comes great potential for anguish. There are a few characteristic issues you need to guard against to write macros well, and, to a lesser extent, even to use macros well.
Name games
~~~~~~~~~~
A lot of these issues are variations on the theme of names not referring to what you intend them to, or in other words, surprise shadowing. For example, the macro below was intended to define a new variable named ``x``, but it ends up modifying a preexisting variable. ::
(defmacro upper-twice [arg]
`(do
(setv x (.upper ~arg))
(+ x x)))
(setv x "Okay guys, ")
(setv salutation (upper-twice "bye"))
(print (+ x salutation))
; Intended result: "Okay guys, BYEBYE"
; Actual result: "BYEBYEBYE"
If you avoid the assignment entirely, by using an argument more than once, you can cause a different problem: surprise multiple evaluation. ::
(defmacro upper-twice [arg]
`(+ (.upper ~arg) (.upper ~arg)))
(setv items ["a" "b" "c"])
(print (upper-twice (.pop items)))
; Intended result: "CC"
; Actual result: "CB"
A better approach is to use :hy:func:`hy.gensym` to choose your variable name::
(defmacro upper-twice [arg]
(setv g (hy.gensym))
`(do
(setv ~g (.upper ~arg))
(+ ~g ~g)))
Hyrule provides some macros that make using gensyms more convenient, like :hy:func:`defmacro! <hyrule.defmacro!>` and :hy:func:`def-gensyms <hyrule.def-gensyms>`.
On the other hand, you can write a macro that advertises a specific name (or set of names) as part of its interface. For example, Hyrule's `anaphoric macro <https://en.wikipedia.org/wiki/Anaphoric_macro>`_ :hy:func:`ap-if <hyrule.ap-if>` assigns the result of a test form to ``it``, and allows the caller to include forms that refer to ``it``::
(import os)
(ap-if (.get os.environ "PYTHONPATH")
(print "Your PYTHONPATH is" it))
Macro subroutines
~~~~~~~~~~~~~~~~~
A case where you could want something to be in the scope of a macro's expansion, and then it turns out not to be, is when you want to call a function or another macro in the expansion::
(defmacro hypotenuse [a b]
(import math)
`(math.sqrt (+ (** ~a 2) (** ~b 2))))
(print (hypotenuse 3 4))
; NameError: name 'math' is not defined
The form ``(import math)`` here appears in the wrong context, in the macro call itself rather than the expansion. You could use ``import`` or ``require`` to bind the module name or one of its members to a gensym, but an often more convenient option is to use the one-shot import syntax :hy:class:`hy.I` or the one-shot require syntax :ref:`hy.R <hy.R>`::
(defmacro hypotenuse [a b]
`(hy.I.math.sqrt (+ (** ~a 2) (** ~b 2))))
(print (hypotenuse 3 4))
A related but distinct issue is when you want to use a function (or other ordinary Python object) in a macro's code, but it isn't available soon enough::
(defn subroutine [x]
(hy.models.Symbol (.upper x)))
(defmacro uppercase-symbol [x]
(subroutine x))
(setv (uppercase-symbol foo) 1)
; NameError: name 'subroutine' is not defined
Here, ``subroutine`` is only defined at run-time, so ``uppercase-symbol`` can't see it when it's expanding (unless you happen to be calling ``uppercase-symbol`` from a different module). This is easily worked around by wrapping ``(defn subroutine …)`` in :hy:func:`eval-and-compile` (or :hy:func:`eval-when-compile` if you want ``subroutine`` to be invisible at run-time).
By the way, despite the need for ``eval-and-compile``, extracting a lot of complex logic out of a macro into a function is often a good idea. Functions are typically easier to debug and to make use of in other macros.
The important take-home big fat WARNINGA typical macro should use only names of these four kinds in its expansion:
- gensyms
- core macros
- objects that Python puts in scope by default (like its built-in functions)
hyand its attributes
It's possible to rebind nearly all these names, so surprise shadowing is still theoretically possible. Unfortunately, the only way to prevent these pathological rebindings from coming about is… don't do that. Don't make a new macro named setv or name a function parameter type unless you're ready for every macro you call to break, the same way you wouldn't monkey-patch a built-in Python module without thinking carefully. This kind of thing is the responsibility of the macro caller; the macro writer can't do much to defend against it. There is at least a pragma :ref:warn-on-core-shadow <warn-on-core-shadow>, enabled by default, that causes defmacro and require to warn you if you give your new macro the same name as a core macro.
.. _reader-macros:
Reader macros
Reader macros allow you to hook into Hy's parser to customize how text is parsed into models. They're defined with :hy:func:defreader <hy.core.macros.defreader>, or, like regular macros, brought in from other modules with :hy:func:require. Rather than receiving function arguments, a reader macro has access to a :py:class:hy.HyReader object named &reader, which provides all the text-parsing logic that Hy uses to parse itself (see :py:class:hy.HyReader and its base class :py:class:hy.Reader for the available methods). A reader macro is called with the hash sign #, and like a regular macro, it should return a model or something convertible to a model.
The simplest kind of reader macro doesn't read anything::
(defreader hi
'(print "Hello."))
#hi #hi #hiA less trivial, and more common, usage of reader macros is to call :func:hy.HyReader.parse_one_form to get a single form from the following source text. Such a reader macro is like a unary regular macro that's called with # instead of parentheses. ::
(defreader do-twice
(setv x (.parse-one-form &reader))
`(do ~x ~x))
#do-twice (print "This line prints twice.")A special feature of reader macros, compared to regular macros, is that if they return None (not to be confused with 'None, a symbol that evaluates to None), no model is produced, as if the reader-macro call wasn't there. ::
(defmacro regular-macro [])
(defreader reader-macro)
(print [1 (regular-macro) 2]) ; => [1, None, 2]
(print [1 #reader-macro 2]) ; => [1, 2]Here's a moderately complex example of a reader macro that couldn't be implemented as a regular macro. It reads in a list of lists in which the inner lists are newline-separated, but newlines are allowed inside elements. ::
(defreader matrix
(.slurp-space &reader)
(setv start (.getc &reader))
(assert (= start "["))
(.slurp-space &reader)
(setv out [[]])
(while (not (.peek-and-getc &reader "]"))
(cond
(any (gfor c " \t" (.peek-and-getc &reader c)))
None
(.peek-and-getc &reader "\n")
(.append out [])
True
(.append (get out -1) (.parse-one-form &reader))))
(lfor line out :if line line))
(print (hy.repr #matrix [
1 (+ 1 1) 3
4 ["element" "containing"
"a" "newline"] 6
7 8 9]))
; => [[1 2 3] [4 ["element" "containing" "a" "newline"] 6] [7 8 9]]Note that because reader macros are evaluated at parse-time, and top-level forms are completely parsed before any further compile-time execution occurs, you can't use a reader macro in the same top-level form that defines it::
(do
(defreader up
(.slurp-space &reader)
(.upper (.read-one-form &reader)))
(print #up "hello?"))
; LexException: reader macro '#up' is not defined
Of the potential problems discussed above that apply to regular macros, such as surprise shadowing, most also apply to reader macros.
.. _macro-namespaces:
Macro namespaces and operations on macros
Macros don't share namespaces with ordinary Python objects. That's why something like (defmacro m []) (print m) fails with a NameError, and how :hy:mod:hy.pyops can provide a function named + without hiding the core macro +.
There are three scoped varieties of regular macro. First are core macros, which are built into Hy; :ref:the set of core macros <core-macros> is fixed. They're available by default. You can inspect them in the dictionary builtins._hy_macros, which is attached to Python's usual :py:mod:builtins module. The keys are strings giving :ref:mangled <mangling> names and the values are the function objects implementing the macros.
Global macros are associated with modules, like Python global variables. They're defined when you call defmacro or require in a global scope. You can see them in the global variable _hy_macros associated with the same module. You can manipulate _hy_macros to list, add, delete, or get help on macros, but be sure to use :hy:func:eval-and-compile or :hy:func:eval-when-compile when you need the effect to happen at compile-time, which is often. (Modifying builtins._hy_macros is of course a risky proposition.) Here's an example, which also demonstrates the core macro :hy:func:get-macro <hy.core.macros.get-macro>. get-macro provides syntactic sugar for getting all sorts of macros as objects. ::
(defmacro m []
"This is a docstring."
'(print "Hello, world."))
(print (in "m" _hy_macros)) ; => True
(help (get-macro m))
(m) ; => "Hello, world."
(eval-and-compile
(del (get _hy_macros "m")))
(m) ; => NameError
(eval-and-compile
(setv (get _hy_macros (hy.mangle "new-mac")) (fn []
'(print "Goodbye, world."))))
(new-mac) ; => "Goodbye, world."Local macros are associated with function, class, or comprehension scopes, like Python local variables. They come about when you call defmacro or require in an appropriate scope. You can call :hy:func:local-macros <hy.core.macros.local-macros> to view local macros, but adding or deleting elements is ineffective. Beware that local macro definitions apply to the results of expanding other macros in the given context, and hence may not be as local as you expect::
(defmacro number []
1)
(defmacro uses-number []
'(number))
(defn f []
(defmacro number []
2)
(uses-number))
(print (uses-number)) ; => 1
(print (f)) ; => 2
(print (uses-number)) ; => 1For this reason, shadowing a core macro is risky even with a local macro.
Finally, _hy_reader_macros is a per-module dictionary like _hy_macros for reader macros, but here, the keys aren't mangled. There are no local reader macros, and there's no official way to introspect on Hy's handful of core reader macros. So, of the three scoped varieties of regular macro, reader macros most resemble global macros.
Model Patterns (`docs/model_patterns.rst`)
============== Model patterns
The module hy.model-patterns provides a library of parser combinators for
parsing complex trees of Hy models. Model patterns exist mostly to help
implement the compiler, but they can also be useful for writing macros.
A motivating example
The kind of problem that model patterns are suited for is the following.
Suppose you want to validate and extract the components of a form like::
(setv form '(try
(foo1)
(foo2)
(except [EType1]
(foo3))
(except [e EType2]
(foo4)
(foo5))
(except []
(foo6))
(finally
(foo7)
(foo8))))You could do this with loops and indexing, but it would take a lot of code and
be error-prone. Model patterns concisely express the general form of a model
tree to be matched, like what a regular expression does for text. Here's a
pattern for a try form of the above kind::
(import
funcparserlib.parser [maybe many]
hy.model-patterns *)
(setv parser (whole [
(sym "try")
(many (notpexpr "except" "else" "finally"))
(many (pexpr
(sym "except")
(| (brackets) (brackets FORM) (brackets SYM FORM))
(many FORM)))
(maybe (dolike "else"))
(maybe (dolike "finally"))]))You can run the parser with (.parse parser form). The result is::
#(
['(foo1) '(foo2)]
[
'([EType1] [(foo3)])
'([e EType2] [(foo4) (foo5)])
'([] [(foo6)])]
None
'((foo7) (foo8)))which is conveniently utilized with an assignment such as (setv [body except-clauses else-part finally-part] result). Notice that else-part
will be set to None because there is no else clause in the original
form.
Usage
Model patterns are implemented as funcparserlib_ parser combinators. We won't
reproduce funcparserlib's own documentation, but here are some important
built-in parsers:
(+ ...)matches its arguments in sequence.(| ...)matches any one of its arguments.(>> parser function)matchesparser, then feeds the result throughfunctionto change the value that's produced on a successful parse.(skip parser)matchesparser, but doesn't add it to the produced
value.(maybe parser)matchesparserif possible. Otherwise, it produces
the valueNone.(some function)takes a predicatefunctionand matches a form if it
satisfies the predicate.
Some of the more important of Hy's own parsers are:
- :data:
FORM <hy.model_patterns.FORM>matches anything. - :data:
SYM <hy.model_patterns.SYM>matches any symbol. - :func:
sym <hy.model_patterns.sym>matches and discards (perskip) the
named symbol or keyword. - :func:
brackets <hy.model_patterns.brackets>matches the arguments in square
brackets. - :func:
pexpr <hy.model_patterns.pexpr>matches the arguments in parentheses.
Here's how you could write a simple macro using model patterns::
(defmacro pairs [#* args]
(import
funcparserlib.parser [many]
hy.model-patterns [whole SYM FORM])
(setv [args] (.parse
(whole [(many (+ SYM FORM))])
args))
`[~@(gfor [a1 a2] args #((str a1) a2))])
(print (hy.repr (pairs a 1 b 2 c 3)))
; => [#("a" 1) #("b" 2) #("c" 3)]A failed parse will raise funcparserlib.parser.NoParseError.
.. _funcparserlib: https://github.com/vlasovskikh/funcparserlib
Reference
.. automodule:: hy.model_patterns
:members:
.. The below must be documented in this file rather than using
autodoc, due to a regression in Python 3.14.
.. data:: FORM
Match any token... data:: SYM
Match a :class:`Symbol <hy.models.Symbol>`... data:: KEYWORD
Match a :class:`Keyword <hy.models.Keyword>`... data:: STR
Match a :class:`String <hy.models.String>`... data:: LITERAL
Match any model type denoting a literal.Repl (`docs/repl.rst`)
.. _repl:
=========== The Hy REPL
Hy's read-eval-print loop <https://en.wikipedia.org/wiki/Read-eval-print_loop>_ (REPL) is implemented in
the class :class:hy.REPL. The REPL can be started interactively
:doc:from the command line <cli> or programmatically with the instance method
:meth:hy.REPL.run.
Two :doc:environment variables <env_var> useful for the REPL areHY_HISTORY, which specifies where the REPL input history is saved, andHYSTARTUP, which specifies :ref:a file to run when the REPL starts <startup-file>.
Due to Python limitations, a Python :class:code.InteractiveConsole
launched inside the Hy REPL, or a Hy REPL inside another Hy REPL, may
malfunction.
.. autoclass:: hy.REPL
:members: run
.. _repl-output-function:
Output functions
By default, the return value of each REPL input is printed with
:hy:func:hy.repr. To change this, you can set the REPL output function with
e.g. the command-line argument --repl-output-fn. Use :func:repr to get
Python representations, like Python's own REPL.
Regardless of the output function, no output is produced when the value isNone, as in Python.
.. _repl-specials:
Special variables
The REPL maintains a few special convenience variables. *1 holds the result
of the most recent input, like _ in the Python REPL. *2 holds the
result of the input before that, and *3 holds the result of the input
before that. Finally, *e holds the most recent uncaught exception.
.. _startup-file:
Startup files
Any macros or Python objects defined in the REPL startup file will be brought
into the REPL's namespace. A few variables are special in the startup file:
repl-spy
If true, print equivalent Python code before executing each piece of Hy code.repl-output-fn
The :ref:output function <repl-output-function>, as a unary callable
object.repl-ps1, repl-ps2
Strings to use as the prompt strings :data:sys.ps1 and
:data:sys.ps2 for the Hy REPL.
Hy startup files can do a number of other things like set banner messages or
change the prompts. The following example shows a number of possibilities::
;; Wrapping in an eval-and-compile ensures these Python packages
;; are available in macros defined in this file as well.
(eval-and-compile
(import sys os)
(sys.path.append "~/"))
(import
re
json
pathlib [Path]
hy.pyops *
hyrule [pp pformat])
(require
hyrule [unless])
(setv
repl-spy True
repl-output-fn pformat
;; Make the REPL prompt => green.
repl-ps1 "\x01\x1b[0;32m\x02=> \x01\x1b[0m\x02"
;; Make the REPL prompt ... red.
repl-ps2 "\x01\x1b[0;31m\x02... \x01\x1b[0m\x02")
(defn slurp [path]
(setv path (Path path))
(when (path.exists)
(path.read-text)))
(defmacro greet [person]
`(print ~person))
Requirements (`docs/requirements.txt`)
Pygments >= 2.18.0
Sphinx == 5.0.2
standard-imghdr
This is needed for old Sphinges on new Pythons.
git+https://github.com/hylang/sphinxcontrib-hydomain.git
Semantics (`docs/semantics.rst`)
============== Semantics
This chapter describes features of Hy semantics that differ from Python's and
aren't better categorized elsewhere, such as in the chapter :doc:macros. Each
is a potential trap for the unwary.
.. contents:: Contents
:local:
.. _implicit-names:
Implicit names
Every compilation unit (basically, module) implicitly begins with (import hy). You can see it in the output of hy2py. The purpose of this is to
ensure Hy can retrieve any names it needs to compile your code. For example,
the code (print '(+ 1 1)) requires constructing a
:class:hy.models.Expression. Thus you should be wary of assigning to the namehy, even locally, because then the wrong thing can happen if the generated
code tries to access hy expecting to get the module. As a bonus, you can
say things like (print (hy.repr #(1 2))) without explicitly importinghy first.
If you restrict yourself to a subset of Hy, it's possible to write a Hy
program, translate it to Python with hy2py, remove the import hy, and
get a working Python program that doesn't depend on Hy itself. Unfortunately,
Python is too dynamic for the Hy compiler to be able to tell in advance when
this will work, which is why the automatic import is unconditional.
Hy needs to create temporary variables to accomplish some of its tricks. For
example, in order to represent (print (with …)) in Python, the result of
the with form needs to be set to a temporary variable. These names begin
with _hy_, so it's wise to avoid this prefix in your own variable names.
Such temporary variables are scoped in the same way surrounding ordinary
variables are, and they aren't explicitly cleaned up, so theoretically, they
can waste memory and lead to :py:meth:object.__del__ being called later than
you expect. When in doubt, check the hy2py output.
.. _order-of-eval:
Order of evaluation
Like many programming languages, but unlike Python, Hy doesn't guarantee in all
cases the order in which function arguments are evaluated. More generally, the
evaluation order of the child models of a :class:hy.models.Sequence is
unspecified. For example, (f (g) (h)) might evaluate (part of) (h)
before (g), particularly if f is a function whereas h is a macro
that produces Python-level statements. So if you need to be sure that g is
called first, call it before f.
When bytecode is regenerated
The first time Hy is asked to execute a file, whether directly or indirectly (as in the case of an import), it will produce a bytecode file
(unless :std:envvar:PYTHONDONTWRITEBYTECODE is set). Subsequently, if the
source file hasn't changed, Hy will load the bytecode instead of recompiling
the source. Python also makes bytecode files, but the difference between recompilation
and loading bytecode is more consequential in Hy because of how Hy lets you run
and generate code at compile-time with things like macros, reader macros, and
:hy:func:eval-and-compile. You may be surprised by behavior like the
following:
.. code-block:: sh
$ echo '(defmacro m [] 1)' >a.hy
$ echo '(require a) (print (a.m))' >b.hy
$ hy b.hy
1
$ echo '(defmacro m [] 2)' >a.hy
$ hy b.hy
1Why didn't the second run of b.hy print 2? Because b.hy was
unchanged, so it didn't get recompiled, so its bytecode still had the old
expansion of the macro m.
Traceback positioning
When an exception results in a traceback, Python uses line and column numbers
associated with AST nodes to point to the source code associated with the
exception:
.. code-block:: text
Traceback (most recent call last):
File "cinco.py", line 4, in <module>
find()
File "cinco.py", line 2, in find
print(chippy)
^^^^^^
NameError: name 'chippy' is not definedThis position information is stored as attributes of the AST nodes. Hy tries to
set these attributes appropriately so that it can also produce correctly
targeted tracebacks, but there are cases where it can't, such as when
evaluating code that was built at runtime out of explicit calls to :ref:model constructors <models>. Python still requires line and column numbers, so Hy
sets these to 1 as a fallback; consequently, tracebacks can point to the
beginning of a file even though the relevant code isn't there.
Syntax (`docs/syntax.rst`)
.. _syntax:
============== Syntax
This chapter describes how Hy source code is understood at the level of text,
as well as the abstract syntax objects that the reader (a.k.a. the parser)
turns text into, as when invoked with :hy:func:hy.read. The basic units of
syntax at the textual level are called forms, and the basic objects
representing forms are called models.
Following Python, Hy is in general case-sensitive. For example, foo andFOO are different symbols, and the Python-level variables they refer to are
also different.
.. contents:: Contents
:local:
.. _models:
An introduction to models
Reading a Hy program produces a nested structure of model objects. Models can
be very similar to the kind of value they represent (such as :class:Integer <hy.models.Integer>, which is a subclass of :class:int) or they can be
somewhat different (such as :class:Set <hy.models.Set>, which is ordered,
unlike actual :class:set\s). All models inherit from :class:Object <hy.models.Object>, which stores textual position information, so tracebacks
can point to the right place in the code. The compiler takes whatever models
are left over after parsing and macro-expansion and translates them into Python
:mod:ast nodes (e.g., :class:Integer <hy.models.Integer> becomes
:class:ast.Constant), which can then be evaluated or rendered as Python code.
Macros (that is, regular macros, as opposed to reader macros) operate on the
model level, taking some models as arguments and returning more models for
compilation or further macro-expansion; they're free to do quite different
things with a given model than the compiler does, if it pleases them to, like
using an :class:Integer <hy.models.Integer> to construct a :class:Symbol <hy.models.Symbol>.
In general, a model doesn't count as equal to the value it represents. For
example, (= (hy.models.String "foo") "foo") returns :data:False. But you
can promote a value to its corresponding model with :hy:func:hy.as-model, or
you can demote a model with the usual Python constructors like :py:class:str
or :py:class:int, or you can evaluate a model as Hy code with
:hy:func:hy.eval.
Models can be created with the constructors, with the :hy:func:quote or
:hy:func:quasiquote macros, or with :hy:func:hy.as-model. Explicit creation
is often not necessary, because the compiler will automatically promote (via
:hy:func:hy.as-model) any object it's trying to evaluate.
Note that when you want plain old data structures and don't intend to produce
runnable Hy source code, you'll usually be better off using Python's basic data
structures (:class:tuple, :class:list, :class:dict, etc.) than models.
Yes, "homoiconicity" is a fun word, but a Hy :class:List <hy.models.List>
won't provide any advantage over a Python :class:list when you're managing a
list of email addresses or something.
The default representation of models (via :hy:func:hy.repr) uses quoting for
readability, so (hy.models.Integer 5) is represented as '5. Python
representations (via :func:repr) use the constructors, and by default are
pretty-printed; you can disable this globally by setting hy.models.PRETTY
to False, or temporarily with the context manager hy.models.pretty.
.. _hyobject:
.. autoclass:: hy.models.Object
.. autoclass:: hy.models.Lazy
Non-form syntactic elements
.. _shebang:
Shebang
If a Hy program begins with ``#!``, Hy assumes the first line is a `shebang
line <https://en.wikipedia.org/wiki/Shebang_(Unix)>`_ and ignores it. It's up
to your OS to do something more interesting with it.
Shebangs aren't real Hy syntax, so :hy:func:`hy.read-many` only allows them
if its option ``skip_shebang`` is enabled.
WhitespaceHy has lax whitespace rules less similar to Python's than to those of most
other programming languages. Whitespace can separate forms (e.g., a b is
two forms whereas ab is one) and it can occur inside some forms (like
string literals), but it's otherwise ignored by the reader, producing no
models.
The reader only grants this special treatment to the ASCII whitespace
characters, namely U+0009 (horizontal tab), U+000A (line feed), U+000B
(vertical tab), U+000C (form feed), U+000D (carriage return), and U+0020
(space). Non-ASCII whitespace characters, such as U+2009 (THIN SPACE), are
treated as any other character. So yes, you can have exotic whitespace
characters in variable names, although this is only especially useful for
obfuscated code contests.
Comments
Comments begin with a semicolon (``;``) and continue through the end of the
line.
There are no multi-line comments in the style of C's ``/* … */``, but you can
use the :ref:`discard prefix <discard-prefix>` or :ref:`string literals
<string-literals>` for similar purposes.
.. _discard-prefix:
Discard prefixLike Clojure, Hy supports the Extensible Data Notation discard prefix #_,
which is kind of like a structure-aware comment. When the reader encounters#_, it reads and then discards the following form. Thus #_ is like; except that reader macros still get executed, and normal parsing resumes
after the next form ends rather than at the start of the next line: [dilly #_ and krunk] is equivalent to [dilly krunk], whereas [dilly ; and krunk] is equivalent to just [dilly. Comments indicated by ; can be
nested within forms discarded by #_, but #_ has no special meaning
within a comment indicated by ;.
Identifiers
Identifiers are a broad class of syntax in Hy, comprising not only variable
names, but any nonempty sequence of characters that aren't ASCII whitespace nor
one of the following: ()[]{};"'`~. Identifiers also aren't recognized if
they parse as something else, like a :ref:keyword <keywords>. The reader will
attempt to read an identifier as each of the following types, in the given
order:
- a :ref:
numeric literal <numeric-literals> - a :ref:
dotted identifier <dotted-identifiers> - a :ref:
symbol <symbols>
.. _numeric-literals:
Numeric literals
All of :ref:`Python's syntax for numeric literals ` is supported in
Hy, resulting in an :class:`Integer <hy.models.Integer>`, :class:`Float
<hy.models.Float>`, or :class:`Complex <hy.models.Complex>`. Hy also provides a
few extensions:
- Commas (``,``) can be used like underscores (``_``) to separate digits
without changing the result. Thus, ``10_000_000_000`` may also be written
``10,000,000,000``. Hy is also more permissive about the placement of
separators than Python: several may be in a row, and they may be after all
digits, after ``.``, ``e``, or ``j``, or even inside a radix prefix. Separators
before the first digit are still forbidden because e.g. ``_1`` is a legal
Python variable name, so it's a symbol in Hy rather than an integer.
- Integers can begin with leading zeroes, even without a radix prefix like
``0x``. Leading zeroes don't automatically cause the literal to be
interpreted in octal like they do in C. For octal, use the prefix ``0o``, as
in Python.
- ``NaN``, ``Inf``, and ``-Inf`` are understood as literals. Each produces a
:class:`Float <hy.models.Float>`. These are case-sensitive, unlike other uses
of letters in numeric literals (``1E2``, ``0XFF``, ``5J``, etc.).
- Hy allows complex literals as understood by the constructor for
:class:`complex`, such as ``5+4j``. (This is also legal Python, but Hy reads
it as a single :class:`Complex <hy.models.Complex>`, and doesn't otherwise
support infix addition or subtraction, whereas Python parses it as an
addition expression.)
.. autoclass:: hy.models.Integer
.. autoclass:: hy.models.Float
.. autoclass:: hy.models.Complex
.. _dotted-identifiers:
Dotted identifiersDotted identifiers are named for their use of the dot character ., also
known as a period or full stop. They don't have their own model type because
they're actually syntactic sugar for :ref:expressions <expressions>. Syntax
like foo.bar.baz is equivalent to (. foo bar baz). The general rule is
that a dotted identifier looks like two or more :ref:symbols <symbols>
(themselves not containing any dots) separated by single dots. The result is an
expression with the symbol . as its first element and the constituent
symbols as the remaining elements.
A dotted identifier may also begin with one or more dots, as in .foo.bar or..foo.bar, in which case the resulting expression has the appropriate head
(. or .. or whatever) and the symbol None as the following element.
Thus, ..foo.bar is equivalent to (.. None foo bar). In the leading-dot
case, you may also use only one constitutent symbol. Thus, .foo is a legal
dotted identifier, and equivalent to (. None foo).
See :ref:the dot macro <dot> for what these expressions typically compile to.
See also the special behavior for :ref:expressions <expressions> that begin
with a dotted identifier that itself begins with a dot. Note that Hy provides
definitions of . and ... by default, but not .., ....,....., etc., so ..foo.bar won't do anything useful by default outside
of macros that treat it specially, like :hy:func:import.
.. _symbols:
Symbols
Symbols are the catch-all category of identifiers. In most contexts, symbols
are compiled to Python variable names, after being :ref:`mangled <mangling>`.
You can create symbol objects with the :hy:func:`quote` operator or by calling
the :class:`Symbol <hy.models.Symbol>` constructor (thus, :class:`Symbol
<hy.models.Symbol>` plays a role similar to the ``intern`` function in other
Lisps). Some example symbols are ``hello``, ``+++``, ``3fiddy``, ``$40``,
``just✈wrong``, and ``🦑``.
Dots are only allowed in a symbol if every character in the symbol is a dot.
Thus, ``a..b`` and ``a.`` are neither dotted identifiers nor symbols; they're
syntax errors.
As a special case, the symbol ``...`` compiles to the :data:`Ellipsis` object,
as in Python.
.. autoclass:: hy.models.Symbol
.. _mangling:
ManglingSince the rules for Hy symbols and keywords are much more permissive than the rules for
Python identifiers, Hy uses a mangling algorithm to convert its own names to
Python-legal names. The steps are as follows:
#. Remove any leading underscores. Underscores are typically the ASCII
underscore _, but they may also be any Unicode character that normalizes
(according to NFKC) to _. Leading underscores have special significance
in Python, and Python normalizes all Unicode before this test, so we'll
process the remainder of the name and then add the leading underscores back
onto the final mangled name.
#. Convert ASCII hyphens (-) to underscores (_). Thus, foo-bar
becomes foo_bar. If the name at this step starts with a hyphen, this
first hyphen is not converted, so that we don't introduce a new leading
underscore into the name. Thus --has-dashes? becomes -_has_dashes?
at this step.
#. If the name still isn't Python-legal, make the following changes. A name
could be Python-illegal because it contains a character that's never legal
in a Python name or it contains a character that's illegal in that position.
- Prepend
hyx_to the name. - Replace each illegal character with
XfooX, wherefoois the Unicode
character name in lowercase, with spaces replaced by underscores and
hyphens replaced byH. Replace leading hyphens andXitself the
same way. If the character doesn't have a name, useUfollowed by its
code point in lowercase hexadecimal.
Thus, green☘ becomes hyx_greenXshamrockX and
-_has_dashes becomes hyx_XhyphenHminusX_has_dashes.
#. Take any leading underscores removed in the first step, transliterate them
to ASCII, and add them back to the mangled name. Thus, __green☘ becomes
__hyx_greenXshamrockX.
#. Finally, normalize any leftover non-ASCII characters. The result may still
not be ASCII (e.g., α is already Python-legal and normalized, so it
passes through the whole mangling procedure unchanged), but it is now
guaranteed that any names are equal as strings if and only if they refer to
the same Python identifier.
You can invoke the mangler yourself with the function :hy:func:hy.mangle, and try to undo this (perhaps not quite successfully) with :hy:func:hy.unmangle.
Mangling isn't something you should have to think about often, but you may see
mangled names in error messages, the output of hy2py, etc. A catch to be
aware of is that mangling, as well as the inverse "unmangling" operation
offered by :hy:func:hy.unmangle, isn't one-to-one. Two different symbols,
like foo-bar and foo_bar, can mangle to the same string and hence
compile to the same Python variable.
.. _keywords:
Keywords
A string of identifier characters starting with a colon (:) and not
containing a dot (.), such as :foo, is a :class:Keyword <hy.models.Keyword>.
Literal keywords are most often used for their special treatment in
:ref:expressions <expressions> that aren't macro calls: they set
:std:term:keyword arguments <keyword argument>, rather than being passed in
as values. For example, (f :foo 3) calls the function f with the
parameter foo set to 3. The keyword is also :ref:mangled <mangling>
at compile-time. To prevent a literal keyword from being treated specially in
an expression, you can :hy:func:quote the keyword, or you can use it as the
value for another keyword argument, as in (f :foo :bar).
Whereas Python requires all positional arguments in a call to precede all
keyword arguments, Hy allows them to mingled, as in (f 1 :foo 2 3). This is
implemented by simply moving the keyword arguments back, as in (f 1 3 :foo 2), with the attendant consequences for order of evaluation (:ref:which shouldn't generally be relied upon in Hy <order-of-eval>).
Otherwise, keywords are simple model objects that evaluate to themselves. Users
of other Lisps should note that it's often a better idea to use a string than a
keyword, because the rest of Python uses strings for cases in which other Lisps
would use keywords. In particular, strings are typically more appropriate than
keywords as the keys of a dictionary. Notice that (dict :a 1 :b 2) is
equivalent to {"a" 1 "b" 2}, which is different from {:a 1 :b 2} (see
:ref:dict-literals).
The empty keyword : is syntactically legal, but you can't compile a
function call with an empty keyword argument because of Python limitations.
Thus (foo : 3) must be rewritten to use runtime unpacking, as in (foo #** {"" 3}).
.. autoclass:: hy.models.Keyword
:members: bool, lt, call
.. _string-literals:
.. _hystring:
String literals
Hy allows double-quoted strings (e.g., "hello"), but not single-quoted
strings like Python. The single-quote character ' is reserved for
preventing the evaluation of a form, (e.g., '(+ 1 1)), as in most Lisps
(see :ref:more-sugar). Python's so-called triple-quoted strings (e.g.,'''hello''' and """hello""") aren't supported, either. However, in Hy, unlike
Python, any string literal can contain newlines; furthermore, Hy has
:ref:bracket strings . For consistency with Python's
triple-quoted strings, all literal newlines in literal strings are read as in"\n" (U+000A, line feed) regardless of the newline style in the actual
code.
String literals support :ref:a variety of backslash escapes .
Unrecognized escape sequences are a syntax error. To create a "raw string" that
interprets all backslashes literally, prefix the string with r, as inr"slash\not".
By default, all string literals are regarded as sequences of Unicode characters.
The result is the model type :class:String <hy.models.String>.
You may prefix a string literal with b to treat it as a sequence of bytes,
producing :class:Bytes <hy.models.Bytes> instead.
Unlike Python, Hy only recognizes string prefixes (r, b, f, t) in
lowercase, and doesn't allow the no-op prefix u.
:ref:F-strings and t-strings <syntax-fstrings> are string-like compound
constructs documented further below.
.. autoclass:: hy.models.String
.. autoclass:: hy.models.Bytes
.. _bracket-strings:
Bracket strings
Hy supports an alternative form of string literal called a "bracket string"
similar to Lua's long brackets. Bracket strings have customizable delimiters,
like the here-documents of other languages. A bracket string begins with
``#[FOO[`` and ends with ``]FOO]``, where ``FOO`` is any string not containing
``[`` or ``]``, including the empty string. (If ``FOO`` is exactly ``f`` or
begins with ``f-``, the bracket string is interpreted as an :ref:`f-string
<syntax-fstrings>`. You can enable an analogous feature for :ref:`t-strings
<syntax-tstrings>` with the :ref:`pragma <bracketed-templates>`
``bracketed-templates``.) For example::
(print #[["That's very kind of yuo [sic]" Tom wrote back.]])
; "That's very kind of yuo [sic]" Tom wrote back.
(print #[==[1 + 1 = 2]==])
; 1 + 1 = 2
Bracket strings are always raw Unicode strings, and don't allow the ``r`` or
``b`` prefixes.
A bracket string can contain newlines, but if it begins with one, the newline
is removed, so you can begin the content of a bracket string on the line
following the opening delimiter with no effect on the content. Any leading
newlines past the first are preserved.
.. _hysequence:
Sequential forms
----------------
Sequential forms (:class:`Sequence <hy.models.Sequence>`) are nested forms
comprising any number of other forms, in a defined order.
.. autoclass:: hy.models.Sequence
.. _expressions:
Expressions
~~~~~~~~~~~
Expressions (:class:`Expression <hy.models.Expression>`) are denoted by
parentheses: ``( … )``. The compiler evaluates expressions by checking the
first element, called the head.
- If the head is a symbol, and the symbol is the name of a currently defined
macro, the macro is called.
- Exception: if the symbol is also the name of a function in
:hy:mod:`hy.pyops`, and one of the arguments is an
:hy:func:`unpack-iterable` form, the ``pyops`` function is called instead
of the macro. This makes reasonable-looking expressions work that would
otherwise fail. For example, ``(+ #* summands)`` is understood as
``(hy.pyops.+ #* summands)``, because Python provides no way to sum a list
of unknown length with a real addition expression.
- If the head is itself an expression of the form ``(. None …)`` (typically
produced with a :ref:`dotted identifier <dotted-identifiers>` like ``.add``),
it's used to construct a method call with the element after ``None`` as the
object: thus, ``(.add my-set 5)`` is equivalent to ``((. my-set add) 5)``,
which becomes ``my_set.add(5)`` in Python.
.. _hy.R:
- Exception: expressions like ``((. hy R module-name macro-name) …)``, or equivalently ``(hy.R.module-name.macro-name …)``, get special treatment. They :hy:func:`require` the module ``module-name`` and call its macro ``macro-name``, so ``(hy.R.foo.bar 1)`` is equivalent to ``(require foo) (foo.bar 1)``, but without bringing ``foo`` or ``foo.bar`` into scope. Thus ``hy.R`` is convenient syntactic sugar for macros you'll only call once in a file, or for macros that you want to appear in the expansion of other macros without having to call :hy:func:`require` in the expansion. As with :hy:class:`hy.I`, dots in the module name must be replaced with slashes.
- Otherwise, the expression is compiled into a Python-level call, with the
head being the calling object. (So, you can call a function that has
the same name as a macro with an expression like ``((do setv) …)``.) The
remaining forms are understood as arguments. Use :hy:func:`unpack-iterable`
or :hy:func:`unpack-mapping` to break up data structures into individual
arguments at runtime.
The empty expression ``()`` is legal at the reader level, but has no inherent
meaning. Trying to compile it is an error. For the empty tuple, use ``#()``.
.. autoclass:: hy.models.Expression
.. _hylist:
List, tuple, and set literals- Literal :class:
list\s (:class:List <hy.models.List>) are denoted by[ … ]. - Literal :class:
tuple\s (:class:Tuple <hy.models.Tuple>) are denoted by#( … ). - Literal :class:
set\s (:class:Set <hy.models.Set>) are denoted by#{ … }.
.. autoclass:: hy.models.List
.. autoclass:: hy.models.Tuple
.. autoclass:: hy.models.Set
.. _dict-literals:
Dictionary literals
Literal dictionaries (:class:`dict`, :class:`Dict <hy.models.Dict>`) are
denoted by ``{ … }``. Even-numbered child forms (counting the first as 0)
become the keys whereas odd-numbered child forms become the values. For
example, ``{"a" 1 "b" 2}`` produces a dictionary mapping ``"a"`` to ``1`` and
``"b"`` to ``2``. Trying to compile a :class:`Dict <hy.models.Dict>` with an
odd number of child models is an error.
As in Python, calling :class:`dict` with keyword arguments may be more
convenient than using a literal dictionary when all the keys are
strings. Compare the following alternatives::
(dict :a 1 :b 2 :c 3 :d 4 :e 5)
{"a" 1 "b" 2 "c" 3 "d" 4 "e" 5}
.. autoclass:: hy.models.Dict
.. _syntax-fstrings:
Format strings and template stringsA format string (or "f-string", or "formatted string literal") is a string
literal with embedded code, possibly accompanied by formatting commands. The
result is an :class:FString <hy.models.FString>, Hy f-strings work much like
:ref:Python f-strings except that the embedded code is in Hy
rather than Python. ::
(print f"The sum is {(+ 1 1)}.") ; => The sum is 2... _syntax-tstrings:
A template string (or "t-string", or "template string literal"; :pep:750;
requires Hy 1.3) is similar but evaluates to a :py:class:Template <string.templatelib.Template> containing the sequence of string and expression
components, without any interpolation. T-strings are modeled as :class:FString <hy.models.FString>\s with the instance variable :is_tstring set toTrue. Hy's syntax and models for t-strings work on any Python version, but
actually compiling a t-string requires Python 3.14 or later. ::
(print (hy.repr t"The sum is {(+ 1 1)}."))
; => (Template "The sum is " (Interpolation 2 "(+ 1 1)") ".")
Since =, !, and : are identifier characters in Hy, Hy decides where
the code in a replacement field ends (and any debugging =, conversion
specifier, or format specifier begins) by parsing exactly one form. You can usedo to combine several forms into one, as usual. Whitespace may be necessary
to terminate the form::
(setv foo "a")
(print f"{foo:x<5}") ; => NameError: name 'hyx_fooXcolonXxXlessHthan_signX5' is not defined
(print f"{foo :x<5}") ; => axxxxUnlike Python, whitespace is allowed between a conversion and a format
specifier.
Also unlike Python, comments and backslashes are allowed in replacement fields.
The same reader is used for the form to be evaluated as for elsewhere in the
language. Thus e.g. f"{"a"}" is legal, and equivalent to "a".
.. autoclass:: hy.models.FString
.. autoclass:: hy.models.FComponent
.. _more-sugar:
Additional sugar
Syntactic sugar is available to construct two-item :ref:expressions <expressions> with certain heads. When the sugary characters are encountered
by the reader, a new expression is created with the corresponding macro name as
the first element and the next parsed form as the second. No parentheses are
required. Thus, since ' is short for quote, 'FORM is read as(quote FORM). Whitespace is allowed, as in ' FORM. This is all resolved
at the reader level, so the model that gets produced is the same whether you
take your code with sugar or without.
========================== ================
Macro Syntax
========================== ================
:hy:func:quote 'FORM
:hy:func:quasiquote ```FORM:hy:func:`unquote` ~FORM:hy:func:`unquote-splice` ~@FORM:hy:func:`unpack-iterable`#* FORM:hy:func:`unpack-mapping` #** FORM``
========================== ================
Reader macros
A hash (#) followed by a :ref:symbol <symbols> invokes the :ref:reader macro <reader-macros> named by the symbol. (Trying to call an undefined reader
macro is a syntax error.) Parsing of the remaining source code is under control
of the reader macro until it returns.
Tutorial (`docs/tutorial.rst`)
======== Tutorial
.. figure:: _static/cuddles-transparent-small.png
:alt: Karen Rustard's Cuddles
Hy's mascot, Cuddles the cuttlefish.
This chapter provides a quick introduction to Hy. It assumes a basic background
in programming, but no specific prior knowledge of Python or Lisp.
.. contents:: Contents
:local:
Lisp-stick on a Python
Let's start with the classic::
(print "Hy, world!")This program calls the :func:print function, which, like all of Python's
:ref:built-in functions <py:built-in-funcs>, is available in Hy.
All of Python's :ref:binary and unary operators <py:expressions> are
available, too, although == is spelled = in deference to Lisp
tradition. Here's how we'd use the addition operator +::
(+ 1 3)This code returns 4. It's equivalent to 1 + 3 in Python and many other
languages. Languages in the Lisp <https://en.wikipedia.org/wiki/Lisp_(programming_language)>_ 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 to1 + 2 + 3.
Here's a more complex example::
(- (* (+ 1 3 88) 2) 8)This code returns 176. Why? You 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 you can pass the --spy option to
Hy when starting the interactive read-eval-print loop (REPL), which shows the
Python equivalent of each input line before the result. (To translate in the
other direction, from Python to Hy, try the external program py2hy <https://github.com/hylang/py2hy>__.) The infix equivalent in this case is:
.. code-block:: python
((1 + 3 + 88) * 2) - 8To 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 88) 2) 8)
(- (* 92 2) 8)
(- 184 8)
176The 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
:ref:expression <expressions> is a form enclosed in parentheses; its first
child form, called the head, determines what the expression does, and
should generally be a function or macro. :py:term:Functions <function>, the
most ordinary sort of head, constitute reusable pieces of code that can take in
arguments and return a value. Macros (described in more detail :ref:below <tutorial-macros>) are a special kind of function that's executed at
compile-time and returns code to be executed at run-time.
Comments start with a ; character and continue till the end of the line. A
comment is functionally equivalent to whitespace. ::
(setv password "susan") ; My daughter's nameAlthough # isn't a comment character in Hy, a Hy program can begin with a
:ref:shebang line <shebang>, which Hy itself will ignore::
#!/usr/bin/env hy
(print "Make me executable, and run me!")
Literals
Hy has :ref:literal syntax <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.
============== ================ =================
Hy Python Type
============== ================ =================1 1 :class:int1.2 1.2 :class:float4j 4j :class:complexTrue True :class:boolNone None NoneType"hy" 'hy' :class:strb"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
============== ================ =================
The Hy REPL prints output in Hy syntax by default, with the function :hy:func:hy.repr::
=> [1 2 3]
[1 2 3]
But if you start Hy like this::
$ hy --repl-output-fn=repr
the REPL will use Python's native :py:func:repr function instead, so you'll see values in Python syntax::
=> [1 2 3]
[1, 2, 3]
Basic operations
Set variables with :hy:func:setv::
(setv zone-plane 8)Access the elements of a list, dictionary, or other data structure with
:hy:func:get <hy.pyops.get>::
(setv fruit ["apple" "banana" "cantaloupe"])
(print (get fruit 0)) ; => apple
(setv (get fruit 1) "durian")
(print (get fruit 1)) ; => durianAccess a range of elements in an ordered structure with
:hy:func:cut <hy.pyops.cut>::
(print (cut "abcdef" 1 4)) ; => bcdConditional logic can be built with :hy:func:if::
(if (= 1 1)
(print "Math works. The universe is safe.")
(print "Math has failed. The universe is doomed."))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.
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 macro
:hy:func:do (known more traditionally in Lisp as progn), which combines
several forms into one, returning the last::
(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.")))
For branching on more than one case, try :hy:func:cond <hy.core.macros.cond>::
(setv somevar 33)
(cond
(> somevar 50)
(print "That variable is too big!")
(< somevar 10)
(print "That variable is too small!")
True
(print "That variable is jussssst right!"))The macro (when CONDITION THEN-1 THEN-2 …) is shorthand for (if CONDITION (do THEN-1 THEN-2 …) None).
Hy's basic loops are :hy:func:while and :hy:func:for::
(setv x 3)
(while (> x 0)
(print x)
(setv x (- x 1))) ; => 3 2 1
(for [x [1 2 3]]
(print x)) ; => 1 2 3A more functional way to iterate is provided by the comprehension forms such as
:hy:func:lfor. Whereas for always returns None, lfor returns a list
with one element per iteration. ::
(print (lfor x [1 2 3] (* x 2))) ; => [2, 4, 6]Functions, classes, and modules
Define named functions with :hy:func:defn::
(defn fib [n]
(if (< n 2)
n
(+ (fib (- n 1)) (fib (- n 2)))))
(print (fib 8)) ; => 21Define anonymous functions with :hy:func:fn::
(print (list (filter (fn [x] (% x 2)) (range 10))))
; => [1, 3, 5, 7, 9]Special symbols in the parameter list of defn or fn allow you to
indicate optional arguments, provide default values, and collect unlisted
arguments::
(defn test [a b [c None] [d "x"] #* 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)]Set a function parameter by name with a :keyword::
(test 1 2 :d "y") ; => [1, 2, None, 'y', ()]Keyword arguments may be placed before or among positional arguments, with the
same effect as putting all the positional arguments first::
(test 1 :d "y" 2) ; => [1, 2, None, 'y', ()]You can unpack iterable objects into positional arguments with #* (:hy:func:unpack-iterable), or dictionary-like objects into keyword arguments with #** (:hy:func:unpack-mapping)::
(setv x [1 2 3])
(setv y {"d" 4})
(test #* x #** y) ; => [1, 2, 3, 4, ()]Note that unlike Python, Hy doesn't always evaluate function arguments (or the
items in a literal list, or the items in a literal dictionary, etc.) :ref:in the order they appear in the code <order-of-eval>. But you can always force a
particular evaluation order with :hy:func:do, or with other macros that
provide an implicit :hy:func:do, like :hy:func:when <hy.core.macros.when>
or :hy:func:fn.
Define classes with :hy:func:defclass::
(defclass FooBar []
(defn __init__ [self x]
(setv self.x x))
(defn get-x [self]
self.x))Here we create a new instance fb of FooBar and access its attributes
with a :ref:dotted identifier <dotted-identifiers> or :ref:the dot macro <dot>::
(setv fb (FooBar 15))
(print fb.x) ; => 15
(print (. fb x)) ; => 15
(print (. fb (get-x)) ; => 15
(print (.get-x fb)) ; => 15
(print (fb.get-x)) ; => 15Note 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 one of
the other options, such as (. FORM x) or (.get-x FORM), or call
:py:func:getattr.
Access an external module, whether written in Python or Hy, with
:hy:func:import::
(import math)
(print (math.sqrt 2)) ; => 1.4142135623730951Or use the one-shot import syntax :hy:class:hy.I::
(print (hy.I.math.sqrt 2))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.
.. _tutorial-macros:
Macros
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::
(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")If you run this program twice in a row, you'll see this:
.. code-block:: text
$ hy example.hy
Now for a slow computation
Done computing
Executing
Value: 1
Done executing
$ hy example.hy
Executing
Value: 1
Done executingThe 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 "Executing")
(print "Value:" 1)
(print "Done executing")Our macro m has an especially simple return value, an integer (:py:class:int), which at
compile-time is converted to an integer model (:class:hy.models.Integer). In general, macros can return
arbitrary Hy models to be executed as code. There are several helper macros that
make it easy to construct forms programmatically, such as :hy:func:quote
('), :hy:func:quasiquote (), :hy:func:`unquote` (``~``), :hy:func:`unquote-splice` (``~@``), and :hy:func:`defmacro! <hyrule.defmacro!>`. The previous chapter has :ref:`a simple example <do-while>` of using and ~@ to define a new control constructdo-while.
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 :hy:func:require <require>,
which imports the module and makes macros available at compile-time.require uses the same syntax as import. ::
(require some-module.macros)
(some-module.macros.rev (1 2 3 +)) ; => 6
Hy also supports reader macros, which are similar to ordinary macros, but
operate on raw source text rather than pre-parsed Hy forms. They can choose how
much of the source code to consume after the point they are called, and return
any code. Thus, reader macros can add entirely new syntax to Hy. For example,
you could add a literal notation for Python's :class:decimal.Decimal class
like so::
(defreader d
(.slurp-space &reader)
`(hy.I.decimal.Decimal ~(.read-ident &reader)))
(print (repr #d .1)) ; => Decimal('0.1')
(import fractions [Fraction])
(print (Fraction #d .1)) ; => 1/10
;; Contrast with the normal floating-point .1:
(print (Fraction .1)) ; => 3602879701896397/36028797018963968require can pull in a reader macro defined in a different module with
syntax like (require mymodule :readers [d]).
Recommended libraries
Hyrule <https://pypi.org/project/hyrule>_ is Hy's standard utility library.
It provides a variety of functions and macros that are useful for writing Hy
programs. ::
(import hyrule [inc])
(list (map inc [1 2 3])) ; => [2 3 4]
(require hyrule [case])
(setv x 2)
(case x 1 "a" 2 "b" 3 "c") ; => "b"toolz <https://pypi.org/project/toolz/>_ and its Cython variant cytoolz <https://pypi.org/project/cytoolz/>_ provide lots of utilities for functional
programming and working with iterables. ::
(import toolz [partition])
(list (partition 2 [1 2 3 4 5 6]))
; => [#(1 2) #(3 4) #(5 6)]metadict <https://pypi.org/project/metadict/>_ allows you to refer to the
elements of a dictionary as attributes. This is handy when frequently referring
to elements with constant strings as keys, since plain indexing is a bit
verbose in Hy. ::
(import metadict [MetaDict])
(setv d (MetaDict))
(setv d.foo 1) ; i.e., (setv (get d "foo") 1)
d.foo ; i.e., (get d "foo")
; => 1
(list (.keys d))
; => ["foo"]Next steps
You now know enough to be dangerous with Hy. You may now smile villainously and
sneak off to your Hydeaway to do unspeakable things.
Refer to Python's documentation for the details of Python semantics. In
particular, :ref:the Python tutorial <tutorial-index> can be helpful even if
you have no interest in writing your own Python code, because it will introduce
you to the semantics, and you'll need a reading knowledge of Python syntax to
understand example code for Python libraries.
Refer to the rest of this manual for Hy-specific features. See the wiki <https://github.com/hylang/hy/wiki/Compatibility-tips>_ for tips
on getting Hy to work with other software. For an official full-blown example
Hy program, see Infinitesimal Quest 2 + ε <http://hylang.org/simalq>_.
Versioning (`docs/versioning.rst`)
============================ Versioning and compatibility
Starting with Hy 1.0.0, Hy is semantically versioned <https://semver.org>. Refer to the NEWS file <https://github.com/hylang/hy/blob/master/NEWS.rst> for a summary of user-visible changes brought on by each version, and how to update your code in case of breaking changes. Be sure you're reading the version of this manual (shown at the top of each page) that matches the version of Hy you're running.
Hy is tested on all released and currently maintained versions of CPython <https://devguide.python.org/versions>_ (on Linux, Windows, and Mac OS), and on recent versions of PyPy <https://pypy.org>. (Pyodide <https://pyodide.org> is also supported, as for Try Hy <http://hylang.org/try-hy>_, but is no longer tested, since the testing infrastructure was a maintenance burden and failed to reveal any compatibility issues in Hy itself.) We usually find that for Hy, unlike most Python packages, we need to change things to fully support each new 3.x release of Python. We may drop compatibility with a version of Python after the CPython guys cease maintaining it. Note that we construe such a change as non-breaking, so we won't bump Hy's major version for it. But we will at least bump the minor version, and python_requires in Hy's setup.py should prevent you from installing a Hy version that won't work with your Python version.
Starting with Hy 1.0.0, each version of Hy also has a nickname, such as "Afternoon Review". Nicknames are used in alphabetical order, with a nickname starting with "Z" then wrapping around to "A". Nicknames are provided mostly for the amusement of the maintainer, but can be useful as a conspicuous sign that you're not using the version you expected. In code, you can get the current nickname as a string (or None, for unreleased commits of Hy) with hy.nickname.
Whyhy (`docs/whyhy.rst`)
======= Why Hy?
.. Changes to the below paragraph should be mirrored on Hy's homepage.
Hy (or "Hylang" for long; named after the insect order Hymenoptera,
since Paul Tagliamonte was studying swarm behavior when he created the
language) is a multi-paradigm general-purpose programming language in
the Lisp family <https://en.wikipedia.org/wiki/Lisp_(programming_language)>_. It's
implemented as a kind of alternative syntax for Python. Compared to
Python, Hy offers a variety of new 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.
.. contents:: Contents
:local:
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,
.. code-block:: python
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 punctuation 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 <https://en.wikipedia.org/wiki/Metaprogramming>_ through :doc:macros <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 #* 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
:keyword: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, :hy:func: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 :hy:func:gfor::
(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),
after importing the function + from the module :hy:mod:hy.pyops.
The Hy compiler works by reading Hy source code into Hy :ref:model objects <models> and compiling them 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 :ref:mix Python and Hy code in the same project, or even the same file, 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 <https://clojure.org>, it is more tightly coupled to Python than
Clojure is to Java; a better analogy is CoffeeScript's <https://coffeescript.org> relationship with 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])) ; 3The same goes for third-party Python libraries from PyPI <https://pypi.org>_
and elsewhere. Here's a tiny CherryPy <https://cherrypy.dev>_ web application
in Hy::
(import cherrypy)
(defclass HelloWorld []
(defn [cherrypy.expose] index [self]
"Hello World!"))
(cherrypy.quickstart (HelloWorld))You can even run Hy on PyPy <https://pypy.org>_ for a particularly speedy
Lisp.
Like all Lisps, Hy is homoiconic <https://en.wikipedia.org/wiki/Homoiconicity>_. 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 <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 :hy:func:hy.eval and Hy will automatically promote them to models.
Hy takes much of its semantics from Python. For example, functions use the same
namespace as objects that aren't functions, so a variable named globals
can shadow the Python built-in function :py:func:globals. 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 <mangling> that transparently converts symbols with names like valid? to
Python-legal identifiers, and a :hy:func:let macro to provide block-level scoping
in place of Python's usual function-level scoping.
What Hy is not
Hy isn't minimal or elegant. Hy is big and ugly and proud of it; it's an
unopinionated big-tent language that lets you do what you want. It has all
of Python's least-motivated semantic features, plus more features, plus
various kinds of syntactic sugar. (The syntax isn't as complex as
Python's, but there are a lot of details beyond plain old S-expressions.)
If you're interested in a more small-and-beautiful approach to Lisp, in
the style of Scheme, check out Hissp <https://github.com/gilch/hissp>_,
another Lisp embedded in Python that was created by a Hy developer.
Also, Hy isn't a reimplementation of an older Lisp. It is its own
language. It looks kind of like Clojure and kind of like Common Lisp, but
nontrivial programs that run in one of these langauges can't be expected
to run on another unaltered.
Static CC0 1.0 (`docs/_static/CC0_1.0.txt`)
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
- Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.
Static Hy Logo About (`docs/_static/hy_logo-about.txt`)
Hy Logo is TeXGyreBonum font with the two parentheses, and two copies
of the lambda character all flipped around and rotated!
Aside from the font design (which was not done by any Hy authors!) the
Hy logo is authored by Christopher Allan Webber in 2013 and released
into the public domain under CC0... see CC0_1.0.txt!
To the extent possible under law, the author(s) have dedicated all
copyright and related and neighboring rights to this logo to
the public domain worldwide. This software is distributed without
any warranty.
You should have received a copy of the CC0 Public Domain
Dedication along with this software. If not, see
http://creativecommons.org/publicdomain/zero/1.0/.
The new Hy logo is Copyright CC-BY-SA 4.0 Kenan Bölükbaşı, thanks, Kenan!
http://www.kenanb.com/posts/Hy-Programming-Language-Logo.html
--- METRICS ---
- Files Extracted: 18
- Estimated Token Budget: ~38099 tokens
- Canonical Reference: https://codewiki.google/github.com/hylang/hy