Hy Documentation
repository·master·Indexed 26 days ago
https://github.com/hylang/hyHy is a Lisp dialect embedded in Python that transforms Lisp code into Python abstract syntax tree (AST) objects. It allows developers to use the entire Python ecosystem using Lisp syntax, featuring macros for sequential and compile-time evaluation, Python code embedding via py and pys, and comprehensive support for Python's control flow, including match statements, comprehensions (lfor, dfor, gfor, sfor), and exception handling.
What's inside Hy
- Hy is a Lisp-family programming language implemented as an alternative syntax for Python. It is not a standalone runtime; instead, it compiles Hy source code into Python Abstract Syntax Tree (AST) objects, which are then executed by the Python interpreter. This allows for direct access to Python's built-ins, data structures, and any third-party libraries available via PyPI. You can mix Python and Hy code within the same project or even the same file.
Use hy.model-patterns for tree parsing
masterThe
hy.model-patternsmodule provides a library of parser combinators designed to parse complex trees of Hy models. It allows you to concisely express the general structure of a model tree (similar to regular expressions for text) to validate and extract components. This is particularly useful for implementing compilers or writing complex macros.To run a parser, use the
.parsemethod on the parser object:(.parse parser form). If the parse fails, it raisesfuncparserlib.parser.NoParseError.(import funcparserlib.parser [maybe many] hy.model-patterns *) (setv form '(try (foo1) (foo2) (except [EType1] (foo3)))) (setv parser (whole [ (sym "try") (many (notpexpr "except" "else" "finally")) (many (pexpr (sym "except") (| (brackets) (brackets FORM) (brackets SYM FORM)) (many FORM)))) ])) (setv result (.parse parser form))Run Hy in the REPL or execute Hy programs
masterAfter installation, you can start an interactive read-eval-print loop (REPL) by running thehycommand. To run a specific Hy script, usehy <filename>.hy.Use comments and discard prefixes in Hy
masterHy provides two ways to comment out code:
- Semicolon (
;): Standard line comments. Everything from the;to the end of the line is ignored. These cannot be used to discard forms mid-structure (e.g.,[dilly ; and krunk]results in an unclosed list[dilly). - Discard Prefix (
#_): An extensible data notation discard prefix. It discards the following single form. Unlike semicolon comments, reader macros are still executed for the discarded form, and parsing resumes immediately after the form ends. This allows for structure-aware commenting (e.g.,[dilly #_ and krunk]is equivalent to[dilly krunk]).
- Semicolon (
Evaluate expressions and method calls
masterExpressions are denoted by parentheses
( ... ). The first element is the head.Evaluation Logic:
- Macros: If the head is a symbol and a macro is defined, the macro is called.
- Exception: If the head is a
hy.pyopsfunction and an argument isunpack-iterable, thepyopsversion is called (e.g.,(+ #* summands)becomes(hy.pyops.+ #* summands)).
- Exception: If the head is a
- Method Calls: If the head is an expression of the form
(. None ...), it constructs a method call.- Example:
(.add my_set 5)is equivalent to((. my_set add) 5), which callsmy_set.add(5)in Python. - Special Case:
(hy.R.module.macro ...)requires the module and calls the macro without bringing it into the local scope.
- Example:
- Standard Calls: Otherwise, the expression is compiled into a Python-level call where the head is the calling object and remaining forms are arguments.
- Macros: If the head is a symbol and a macro is defined, the macro is called.
Understand Hy versioning and Python compatibility
masterHy follows semantic versioning (SemVer).
- Breaking Changes: For a summary of user-visible changes and instructions on how to update code during breaking changes, refer to the
NEWS.rstfile in the repository. - Python Compatibility: Hy is tested on all released and maintained versions of CPython (Linux, Windows, Mac OS) and recent versions of PyPy.
- Version Drops: Hy may drop support for Python versions after CPython ceases maintenance. Such changes are considered non-breaking and will result in a minor version bump rather than a major version bump.
- Installation Safety: The
python_requiresfield in Hy'ssetup.pyis used to prevent installing a version of Hy that is incompatible with your current Python version.
- Breaking Changes: For a summary of user-visible changes and instructions on how to update code during breaking changes, refer to the
Use sequential forms and literals
masterHy uses specific syntax for different collection types:
- Lists: Denoted by
[ ... ](e.g.,[1 2 3]). - Tuples: Denoted by
#( ... )(e.g.,#(1 2 3)). Note:()is a legal empty expression at the reader level but cannot be compiled; use#( )for an empty tuple. - Sets: Denoted by
#{ ... }(e.g.,#{1 2 3}). - Dictionaries: Denoted by
{ ... }. Even-numbered child forms are keys, odd-numbered are values (e.g.,{"a" 1 "b" 2}). - Sequences: Nested forms comprising any number of other forms in a defined order.
- Lists: Denoted by
Install Hy
masterInstall the latest release of Hy using
pip3. It is recommended to use the--userflag to install it for the current user.pip3 install --user hyUse F-strings and T-strings
masterHy provides string-like compound constructs for interpolation.
F-strings (Format Strings):
- Prefix with
f. - Embedded code is written in Hy, not Python.
- Whitespace Rule: Because
=,!, and:are identifier characters, you may need whitespace to separate a conversion specifier from a format specifier. - Example:
f"{foo :x<5}"
T-strings (Template Strings):
- Prefix with
t(requires Hy 1.3; compilation requires Python 3.14+). - Evaluates to a
string.templatelib.Templateobject containing string and expression components without immediate interpolation.
Examples:
(print f"The sum is {(+ 1 1)}.") (print (hy.repr t"The sum is {(+ 1 1)}."))- Prefix with
Compare Hy syntax to Python
masterHy uses Lisp's traditional prefix syntax with parentheses instead of Python's C-like infix syntax. Because structure is indicated by punctuation rather than whitespace, Hy is free-form and convenient for command-line use.
Key syntactic differences include:
- Prefix Notation:
(print "The answer is" (+ 2 (.method object arg)))instead ofprint("The answer is", 2 + object.method(arg)). - Expression-based
with: Unlike Python, Hy'swithform returns the value of its last body form, allowing it to be used in expressions. - Generalized Operators: Binary operators can take more than two arguments (e.g.,
(+ 1 2 3)) and are available as first-class functions (e.g.,+fromhy.pyops).
- Prefix Notation:
Understand Hy Models and their relationship to Python values
masterHy programs are parsed into a nested structure of models. Models represent the abstract syntax of the code. While many models are subclasses of Python types (e.g.,
hy.models.Integeris a subclass ofint), a model is not strictly equal to the value it represents. For example,(= (hy.models.String "foo") "foo")returnsFalsebecause one is a model and the other is a raw Python string.To bridge the gap between models and Python values, you can:
- Promote a value to a model using
hy.as-model. - Demote a model to a Python value using standard Python constructors like
str()orint(). - Evaluate a model as Hy code using
hy.eval.
Note: If you are managing plain data (like a list of email addresses) and do not need to generate Hy source code, use standard Python data structures (
list,dict,tuple) instead of Hy models (hy.models.List, etc.) for better performance and simplicity.- Promote a value to a model using
Access Python reserved words from Hy using Keyword Mincing
masterIf you need to refer to a Python variable that has the same name as a Hy reserved word (e.g.,
break), you can use Unicode normalization (NFKC) to create a valid Python identifier. For example, while(setv break 13)is valid Hy,my_module.breakis invalid Python. You can use mathematical bold small letters to bypass this:𝐚𝐛𝐜𝐝𝐞𝐟𝐠𝐡𝐢𝐣𝐤𝐥𝐦𝐧𝐨𝐩𝐪𝐫𝐬𝐭𝐮𝐯𝐰𝐱𝐲𝐳𝐚𝐛𝐜𝐝𝐞𝐟𝐠𝐡𝐢𝐣𝐤𝐥𝐦𝐧𝐨𝐩𝐪𝐫𝐬𝐭𝐮𝐯𝐰𝐱𝐲𝐳