API¶
Core Macros¶
The following macros are auto imported into all Hy modules as their
base names, such that hy.core.macros.foo
can be called as just foo
.
- #^¶
The
#^
symbol is used to denote annotations in three different contexts:Standalone variable annotations.
Variable annotations in a setv call.
Function argument annotations.
They implement PEP 526 and PEP 3107.
Syntax sugar for
annotate
where the type comes first.Here is some example syntax of all three usages:
Examples
; Annotate the variable x as an int (equivalent to `x: int`). #^int x ; Can annotate with expressions if needed (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))
The rules are:
The type to annotate with is the form that immediately follows the caret.
The annotation always comes (and is evaluated) before the value being annotated. This is unlike Python, where it comes and is evaluated after the value being annotated.
For annotating items with generic types, the
of
macro will likely be of use.
- (annotate value type)¶
Expanded form of
#^
. Syntactically equal to#^
and usable wherever you might use#^
:(setv (annotate x int) 1) (setv #^int x 1) ; the type comes first when using #^int (defn (annotate add1 int) [(annotate x int)] (+ x 1))
- .¶
New in version 0.10.0.
.
is used to perform attribute access on objects. It uses a small DSL to allow quick access to attributes and items in a nested data structure.Examples
(. foo (bar "qux") baz [(+ 1 2)] frob)
Compiles down to:
foo.bar("qux").baz[1 + 2].frob
.
compiles its first argument (in the example, foo) as the object on which to do the attribute dereference. It uses bare symbols as attributes to access (in the example, baz, frob), Expressions as method calls (as in bar), and compiles the contents of lists (in the example,[(+ 1 2)]
) for indexation. Other arguments raise a compilation error.Access to unknown attributes raises an
AttributeError
. Access to unknown keys raises anIndexError
(on lists and tuples) or aKeyError
(on dictionaries).
- (fn name #* arags)¶
fn
, like Python’slambda
, can be used to define an anonymous function. Unlike Python’slambda
, the body of the function can comprise several statements. The parameters are similar todefn
: the first parameter is vector of parameters and the rest is the body of the function.fn
returns a new function. In the following example, an anonymous function is defined and passed to another function for filtering output:=> (setv people [(dict :name "Alice" :age 20) ... (dict :name "Bob" :age 25) ... (dict :name "Charlie" :age 50) ... (dict :name "Dave" :age 5)]) => (defn display-people [people filter] ... (for [person people] (if (filter person) (print (:name person))))) => (display-people people (fn [person] (< (:age person) 25))) Alice Dave
Just as in normal function definitions, if the first element of the body is a string, it serves as a docstring. This is useful for giving class methods docstrings:
=> (setv times-three ... (fn [x] ... "Multiplies input by three and returns the result." ... (* x 3)))
This can be confirmed via Python’s built-in
help
function:=> (help times-three) Help on function times_three: times_three(x) Multiplies input by three and returns result (END)
- (fn/a name #* args)¶
fn/a
is a variant offn
than defines an anonymous coroutine. The parameters are similar todefn/a
: the first parameter is vector of parameters and the rest is the body of the function.fn/a
returns a new coroutine.
- (defn name #* args)¶
Define name as a function with args as the signature, annotations, and body.
defn
is used to define functions. It requires two arguments: a name (given as a symbol) and a list of parameters (also given as symbols). Any remaining arguments constitute the body of the function:(defn name [params] bodyform1 bodyform2...)
If there at least two body forms, and the first of them is a string literal, this string becomes the docstring of the function.
defn
accepts two additional, optional arguments: a bracketed list of decorators and an annotation (see^
) for the return value. These are placed before the function name (in that order, if both are present):(defn [decorator1 decorator2] ^annotation name [params] …)
Parameters may be prefixed with the following special symbols. If you use more than one, they can only appear in the given order (so all positional only arguments must precede
/
, all positional or keyword arguments must precede a#*
rest parameter or*
kwonly delimiter and#**
must be the last argument). This is the same order that Python requires.- /
The preceding parameters can only be supplied as positional arguments.
- positional or keyword arguments:
All parameters until following
/
(if its supplied) but before*/#*/#**
can be supplied positionally or by keyword. Optional arguments may be given as two-argument lists, where the first element is the parameter name and the second is the default value. When defining parameters, a positional argument cannot follow a keyword argument.The following example defines a function with one required positional argument as well as three optional arguments. The first optional argument defaults to
None
and the latter two default to\"(\"
and\")\"
, respectively:=> (defn format-pair [left-val [right-val None] [open-text \"(\"] [close-text \")\"]] ... (+ open-text (str left-val) \", \" (str right-val) close-text)) => (format-pair 3) \"(3, None)\" => (format-pair \"A\" \"B\") \"(A, B)\" => (format-pair \"A\" \"B\" \"<\" \">\") \"<A, B>\" => (format-pair \"A\" :open-text \"<\" :close-text \">\") \"<A, None>\"
- #*
The following parameter will contain a list of 0 or more positional arguments. No other positional parameters may be specified after this one. Parameters defined after this but before
#**
are considered keyword only.The following code example defines a function that can be given 0 to n numerical parameters. It then sums every odd number and subtracts every even number:
=> (defn zig-zag-sum [#* numbers] (setv odd-numbers (lfor x numbers :if (% x 2) x) even-numbers (lfor x numbers :if (= (% x 2) 0) x)) (- (sum odd-numbers) (sum even-numbers))) => (zig-zag-sum) 0 => (zig-zag-sum 3 9 4) 8 => (zig-zag-sum 1 2 3 4 5 6) -3
All following parmaeters can only be supplied as keywords. Like keyword arguments, the parameter may be marked as optional by declaring it as a two-element list containing the parameter name following by the default value. Parameters without a default are considered required:
=> (defn compare [a b * keyfn [reverse False]] ... (setv result (keyfn a b)) ... (if (not reverse) ... result ... (- result))) => (compare \"lisp\" \"python\" ... :keyfn (fn [x y] ... (reduce - (map (fn [s] (ord (get s 0))) [x y])))) -4 => (compare \"lisp\" \"python\" ... :keyfn (fn [x y] ... (reduce - (map (fn [s] (ord (get s 0))) [x y]))) ... :reverse True) 4
=> (compare \"lisp\" \"python\") Traceback (most recent call last): File \"<input>\", line 1, in <module> TypeError: compare() missing 1 required keyword-only argument: 'keyfn'
- #**
Like
#*
, but for keyword arguments. The following parameter will contain 0 or more keyword arguments.The following code examples defines a function that will print all keyword arguments and their values:
=> (defn print-parameters [#** kwargs] ... (for [#(k v) (.items kwargs)] (print k v))) => (print-parameters :parameter-1 1 :parameter-2 2) parameter_1 1 parameter_2 2 ; to avoid the mangling of '-' to '_', use unpacking: => (print-parameters #** {\"parameter-1\" 1 \"parameter-2\" 2}) parameter-1 1 parameter-2 2
Note
Parameter names cannot be Python reserved words nor can a function be called with keyword arguments that are Python reserved words. This means that the following will raise a SyntaxError as they would in Python:
(defn afunc [a b if]) Traceback (most recent call last): File "<stdin>", line 1 (defn afunc [a b if]) ^ hy.errors.HySyntaxError: parameter name cannot be Python reserved word (dict :a 1 :from 2) Traceback (most recent call last): File "<stdin>", line 1 (dict :a 1 :from 2) ^ hy.errors.HySyntaxError: keyword argument cannot be Python reserved word
This only applies to parameter names and a keyword argument name. The value of the parameter or keyword argument can still be a keyword of a reserved word:
=> (defn test [a] a) => (test :a :from) :from
- (defn/a name lambda-list #* body)¶
Define name as a function with lambda-list signature and body body.
defn/a
macro is a variant ofdefn
that instead defines coroutines. It takes three parameters: the name of the function to define, a vector of parameters, and the body of the function:- Examples:
=> (defn/a name [params] body)
- (defmacro name lambda-list #* body)¶
defmacro
is used to define macros. The general format is(defmacro name [parameters] expr)
.The following example defines a macro that can be used to swap order of elements in code, allowing the user to write code in infix notation, where operator is in between the operands.
Examples
=> (defmacro infix [code] ... (quasiquote ( ... (unquote (get code 1)) ... (unquote (get code 0)) ... (unquote (get code 2)))))
=> (infix (1 + 1)) 2
Note
because all values are passed to macros unevaluated,
defmacro
cannot use keyword arguments, or kwargs. All arguments are passed in positionally. Parameters can still be given default values however:=> (defmacro a-macro [a [b 1]] ... `[~a ~b]) => (a-macro 2) [2 1] => (a-macro 2 3) [2 3] => (a-macro :b 3) [:b 3]
- (if test then else)¶
if
compiles to anif
expression (or compoundif
statement). The formtest
is evaluated and categorized as true or false according tobool
. If the result is true,then
is evaluated and returned. Othewise,else
is evaluated and returned.(if (has-money-left account) (print "Let's go shopping!") (print "Back to work."))
See also:
- (await obj)¶
await
creates an await expression. It takes exactly one argument: the object to wait for.Examples
=> (import asyncio) => (defn/a main [] ... (print "hello") ... (await (asyncio.sleep 1)) ... (print "world")) => (asyncio.run (main)) hello world
- (break)¶
break
compiles to abreak
statement, which terminates the enclosing loop. The following example has an infinitewhile
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 ablock
and useblock-ret
instead ofbreak
, or enclose it in a function and usereturn
.
- (chainc #* args)¶
chainc
creates a 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 ofchainc
is to construct chains of heterogeneous operators, such asx <= 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 thaty
is only evaluated once.Each
ARG
is an arbitrary form, which does not itself use infix syntax. Usepy
if you want fully Python-style operator syntax. You can also nestchainc
forms, although this is rarely useful. EachOP
is a literal comparison operator; other forms that resolve to a comparison operator are not allowed.At least two
ARG
s and oneOP
are required, and everyOP
must be followed by anARG
.As elsewhere in Hy, the equality operator is spelled
=
, not==
as in Python.
- (continue)¶
continue
compiles to acontinue
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 ablock
, as in(for [x xs] (block (for [y ys] …)))
. You can then useblock-ret
in place ofcontinue
.
- (do #* body)¶
do
(calledprogn
in some Lisps) takes any number of forms, evaluates them, and returns the value of the last one, orNone
if no forms were provided.Examples
=> (+ 1 (do (setv x (+ 1 1)) x)) 3
- (for #* args)¶
for
is used to evaluate some forms for each element in an iterable object, such as a list. The return values of the forms are discarded and thefor
form returnsNone
.=> (for [x [1 2 3]] ... (print "iterating") ... (print x)) iterating 1 iterating 2 iterating 3
In its square-bracketed first argument,
for
allows the same types of clauses aslfor
.=> (for [x [1 2 3] :if (!= x 2) y [7 8]] ... (print x y)) 1 7 1 8 3 7 3 8
Furthermore, the last argument of
for
can be an(else …)
form. This form is executed after the last iteration of thefor
's outermost iteration clause, but only if that outermost loop terminates normally. If it’s jumped out of with e.g.break
, theelse
is ignored.=> (for [element [1 2 3]] (if (< element 3) ... (print element) ... (break)) ... (else (print "loop finished"))) 1 2 => (for [element [1 2 3]] (if (< element 4) ... (print element) ... (break)) ... (else (print "loop finished"))) 1 2 3 loop finished
- (assert condition [label None])¶
assert
is used to verify conditions while the program is running. If the condition is not met, anAssertionError
is raised.assert
may take one or two parameters. The first parameter is the condition to check, and it should evaluate to eitherTrue
orFalse
. The second parameter, optional, is a label for the assert, and is the string that will be raised with theAssertionError
. For example:Examples
(assert (= variable expected-value)) (assert False) ; AssertionError (assert (= 1 2) "one should equal two") ; AssertionError: one should equal two
- (global sym)¶
global
can be used to mark a symbol as global. This allows the programmer to assign a value to a global symbol. Reading a global symbol does not require theglobal
keyword – only assigning it does.The following example shows how the global symbol
a
is assigned a value in a function and is later on printed in another function. Without theglobal
keyword, the second function would have raised aNameError
.Examples
(defn set-a [value] (global a) (setv a value)) (defn print-a [] (print a)) (set-a 5) (print-a)
- (get coll key1 #* keys)¶
get
is used to access single elements in collections.get
takes at least two parameters: the data structure and the index or key of the item. It will then return the corresponding value from the collection. If multiple index or key values are provided, they are used to access successive elements in a nested structure. Example usage:Examples
=> (do ... (setv animals {"dog" "bark" "cat" "meow"} ... numbers #("zero" "one" "two" "three") ... nested [0 1 ["a" "b" "c"] 3 4]) ... (print (get animals "dog")) ... (print (get numbers 2)) ... (print (get nested 2 1))) bark two b
Note
get
raises a KeyError if a dictionary is queried for a non-existing key.Note
get
raises an IndexError if a list or a tuple is queried for an index that is out of bounds.
- (import #* forms)¶
import
compiles to animport
statement, which makes objects in a different module available in the current module. 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 dir? isfile]) ;; Import with an alias ;; Python: import sys as systest (import sys :as systest) ;; 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 (import tests.resources [kwtest function-with-a-dash] os.path [exists isdir :as dir? isfile :as file?] sys :as systest) ;; Import all module functions into current namespace ;; Python: from sys import * (import sys *)
__all__
can be set to control what’s imported byimport *
, as in Python, but beware that all names in__all__
must be mangled. The macroexport
is a handy way to set__all__
in a Hy program.
- (eval-and-compile #* body)¶
eval-and-compile
is a special form that takes any number of forms. The input forms are evaluated as soon as theeval-and-compile
form is compiled, instead of being deferred until run-time. The input forms are also left in the program so they can be executed at run-time as usual. So, if you compile and immediately execute a program (as callinghy foo.hy
does whenfoo.hy
doesn’t have an up-to-date byte-compiled version),eval-and-compile
forms will be evaluated twice.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 ineval-and-compile
,m
wouldn’t be able to calladd
, because when the compiler was expanding(m 3)
,add
wouldn’t exist yet.
- (eval-when-compile #* body)¶
eval-when-compile
is likeeval-and-compile
, but the code isn’t executed at run-time. Hence,eval-when-compile
doesn’t directly contribute any code to the final program, although it can still change Hy’s state while compiling (e.g., by defining a function).Examples
(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
- (lfor binding iterable #* body)¶
The comprehension forms
lfor
,sfor
,dfor
,gfor
, andfor
are used to produce various kinds of loops, including Python-style comprehensions.lfor
in particular creates a list comprehension. A simple use oflfor
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)
andy (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, andCLAUSES
is any number of clauses. There are several types of clauses:Iteration clauses, which look like
LVALUE ITERABLE
. TheLVALUE
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.:do FORM
, which simply evaluates theFORM
. If you use(continue)
or(break)
here, they 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 (if (not CONDITION) (continue))
.
For
lfor
,sfor
,gfor
, anddfor
, variables defined by an iteration clause or:setv
are not visible outside the form. However, variables defined within the body, such as via asetx
expression, will be visible outside the form. By contrast, iteration and:setv
clauses forfor
share the caller’s scope and are visible outside the form.
- (dfor binding iterable #* body)¶
dfor
creates a dictionary comprehension. Its syntax is the same as that of :hy:func:`lfor except that the final value form must be a literal list of two elements, the first of which becomes each key and the second of which becomes each value.Examples
=> (dfor x (range 5) [x (* x 10)]) {0 0 1 10 2 20 3 30 4 40}
- (gfor binding iterable #* body)¶
gfor
creates a generator expression. Its syntax is the same as that oflfor
. The difference is thatgfor
returns an iterator, which evaluates and yields values one at a time.Examples
=> (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]
- (sfor binding iterable #* body)¶
sfor
creates a set comprehension.(sfor CLAUSES VALUE)
is equivalent to(set (lfor CLAUSES VALUE))
. Seelfor
.
- (setv #* args)¶
setv
is used to bind a value, object, or function to a symbol.Examples
=> (setv names ["Alice" "Bob" "Charlie"]) => (print names) ['Alice', 'Bob', 'Charlie'] => (setv counter (fn [collection item] (.count collection item))) => (counter [1 2 3 4 5 2 3] 2) 2
You can provide more than one target–value pair, and the assignments will be made in order:
=> (setv x 1 y x x 2) => (print x y) 2 1
You can perform parallel assignments or unpack the source value with square brackets and
unpack-iterable
:=> (setv duo ["tim" "eric"]) => (setv [guy1 guy2] duo) => (print guy1 guy2) tim eric => (setv [letter1 letter2 #* others] "abcdefg") => (print letter1 letter2 others) a b ['c', 'd', 'e', 'f', 'g']
- (setx #* args)¶
Whereas
setv
creates an assignment statement,setx
creates an assignment expression (see PEP 572). It requires Python 3.8 or later. Only one target–value pair is allowed, and the target must be a bare symbol, but thesetx
form returns the assigned value instead ofNone
.Examples
=> (when (> (setx x (+ 1 2)) 0) ... (print x "is greater than 0")) 3 is greater than 0
- (let bindings #* body)¶
let
creates lexically-scoped names for local variables. This form takes a list of binding pairs followed by a body which gets executed. A let-bound name ceases to refer to that local outside thelet
form, but arguments in nested functions and bindings in nestedlet
forms can shadow these names.Examples
=> (let [x 5 ; creates new local bound names 'x and 'y y 6] ... (print x y) ... (let [x 7] ; new local and name binding that shadows 'x ... (print x y)) ... (print x y)) ; 'x refers to the first local again 5 6 7 6 5 6
let
can also bind names using Python’s extended iterable unpacking syntax to destructure iterables:=> (let [[head #* tail] #(0 1 2)] ... [head tail]) [0 [1 2]]
Basic assignments (e.g.
setv
,+=
) will update the local variable named by a let binding when they assign to a let-bound name. But assignments viaimport
are always hoisted to normal Python scope, and likewise,defn
ordefclass
will assign the function or class in the Python scope, even if it shares the name of a let binding. To avoid this hoisting, useimportlib.import_module
,fn
, ortype
(or whatever metaclass) instead.If
lfor
,sfor
,dfor
, orgfor
(but notfor
) is in the body of alet
, 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 thelet
ends. To ensure there are no references tolet
-bound objects as soon as possible, usedel
at the end of thelet
, or wrap thelet
in a function.
- (match subject #* cases)¶
The
match
form creates a match statement. 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. Thematch
form returns the value of the corresponding result, orNone
if no case matched. For example:=> (match (+ 1 1) ... 1 "one" ... 2 "two" ... 3 "three") "two"
You can use
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
- (defclass class-name super-classes #* body)¶
New classes are declared with
defclass
. It can take optional parameters in the following order: a list defining (a) possible super class(es) and a string (docstring). The class name may also be preceded by a list of decorators, as indefn
.Examples
=> (defclass class-name [super-class-1 super-class-2] ... "docstring" ... ... (setv attribute1 value1) ... (setv attribute2 value2) ... ... (defn method [self] (print "hello!")))
Both values and functions can be bound on the new class as shown by the example below:
=> (defclass Cat [] ... (setv age None) ... (setv colour "white") ... ... (defn speak [self] (print "Meow"))) => (setv spot (Cat)) => (setv spot.colour "Black") => (.speak spot) Meow
- (del object)¶
New in version 0.9.12.
del
removes an object from the current namespace.Examples
=> (setv foo 42) => (del foo) => foo Traceback (most recent call last): File "<console>", line 1, in <module> NameError: name 'foo' is not defined
del
can also remove objects from mappings, lists, and more.=> (setv test (list (range 10))) => test [0 1 2 3 4 5 6 7 8 9] => (del (cut test 2 4)) ;; remove items from 2 to 4 excluded => test [0 1 4 5 6 7 8 9] => (setv dic {"foo" "bar"}) => dic {"foo" "bar"} => (del (get dic "foo")) => dic {}
- (nonlocal object)¶
New in version 0.11.1.
nonlocal
can be used to mark a symbol as not local to the current scope. The parameters are the names of symbols to mark as nonlocal. This is necessary to modify variables through nestedfn
scopes:Examples
(defn some-function [] (setv x 0) (register-some-callback (fn [stuff] (nonlocal x) (setv x stuff))))
Without the call to
(nonlocal x)
, the inner function would redefinex
tostuff
inside its local scope instead of overwriting thex
in the outer function.See PEP3104 for further information.
- (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; usepys
if you want to use Python statements. The value of the expression is returned from thepy
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.eval
, and related tools to construct thepy
form. If having to backslash-escape internal double quotes is getting you down, try a bracket string. If you want to evaluate some Python code that’s only defined at run-time, try the standard Python functioneval()
.Python code need not syntactically round-trip if you use
hy2py
on a Hy program that usespy
orpys
. For example, comments will be removed.
- (pys string)¶
As
py
, but the code can consist of zero or more statements, including compound statements such asfor
anddef
.pys
always returnsNone
. Also, the code string is dedented withtextwrap.dedent()
before parsing, which allows you to intend the code to match the surrounding Hy code, but significant leading whitespace in embedded string literals will be removed.(pys "myvar = 5") (print "myvar is" myvar)
- (quasiquote form)¶
quasiquote
allows you to quote a form, but also selectively evaluate expressions. Expressions inside aquasiquote
can be selectively evaluated usingunquote
(~
). The evaluated form can also be spliced usingunquote-splice
(~@
). Quasiquote can be also written using the backquote (`
) symbol.Examples
;; let `qux' be a variable with value (bar baz) `(foo ~qux) ; equivalent to '(foo (bar baz)) `(foo ~@qux) ; equivalent to '(foo bar baz)
- (quote form)¶
quote
returns the form passed to it without evaluating it.quote
can alternatively be written using the apostrophe ('
) symbol.Examples
=> (setv x '(print "Hello World")) => x ; variable x is set to unevaluated expression hy.models.Expression([ hy.models.Symbol('print'), hy.models.String('Hello World')]) => (hy.eval x) Hello World
- (require #* args)¶
require
is used to import macros and reader macros from one or more given modules. It allows parameters in all the same formats asimport
.require
imports each named module and then makes each requested macro available in the current module.The following are all equivalent ways to call a macro named
foo
in the modulemymodule
.Examples
(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)
Reader macros are required using
:readers [...]
. The:macros
kwarg can be optionally added for readability:=> (require mymodule :readers *) => (require mymodule :readers [!]) => (require mymodule [foo] :readers [!]) => (require mymodule :readers [!] [foo]) => (require mymodule :macros [foo] :readers [!])
Do note however, that requiring
:readers
, but not specifying any regular macros, will not bring that module’s macros in under their absolute paths:=> (require mymodule :readers [!]) => (mymodule.foo) Traceback (most recent call last): File "stdin-cd49eaaabebc174c87ebe6bf15f2f8a28660feba", line 1, in <module> (mymodule.foo) NameError: name 'mymodule' is not defined
Unlike requiring regular macros, reader macros cannot be renamed with
:as
, and are not made available under their absolute paths to their source module:=> (require mymodule :readers [!]) HySyntaxError: ... => (require mymodule :readers [! :as &]) HySyntaxError: ... => (require mymodule) => mymodule.! x NameError: name 'mymodule' is not defined
To define which macros are collected by
(require mymodule *)
, set the variable_hy_export_macros
(analogous to Python’s__all__
) to a list of mangled macro names, which is accomplished most conveniently withexport
. The default behavior is to collect all macros other than those whose mangled names begin with an ASCII underscore (_
).When requiring reader macros,
(require mymodule :readers *)
will collect all reader macros both defined and required withinmymodule
.Macros that call macros
One aspect of
require
that may be surprising is what happens when one macro’s expansion calls another macro. Supposemymodule.hy
looks like this:(defmacro repexpr [n expr] ; Evaluate the expression n times ; and collect the results in a list. `(list (map (fn [_] ~expr) (range ~n)))) (defmacro foo [n] `(repexpr ~n (input "Gimme some input: ")))
And then, in your main program, you write:
(require mymodule [foo]) (print (mymodule.foo 3))
Running this raises
NameError: name 'repexpr' is not defined
, even though writing(print (foo 3))
inmymodule
works fine. The trouble is that your main program doesn’t have the macrorepexpr
available, since it wasn’t imported (and imported under exactly that name, as opposed to a qualified name). You could do(require mymodule *)
or(require mymodule [foo repexpr])
, but a less error-prone approach is to change the definition offoo
to require whatever sub-macros it needs:(defmacro foo [n] `(do (require mymodule) (mymodule.repexpr ~n (input "Gimme some input: "))))
It’s wise to use
(require mymodule)
here rather than(require mymodule [repexpr])
to avoid accidentally shadowing a function namedrepexpr
in the main program.Note
Qualified macro names
Note that in the current implementation, there’s a trick in qualified macro names, like
mymodule.foo
andM.foo
in the above example. These names aren’t actually attributes of module objects; they’re just identifiers with periods in them. In fact,mymodule
andM
aren’t defined by theserequire
forms, even at compile-time. None of this will hurt you unless try to do introspection of the current module’s set of defined macros, which isn’t really supported anyway.
- (return object)¶
return
compiles to areturn
statement. It exits the current function, returning its argument if provided with one orNone
if not.Examples
=> (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, since the last form of a function is returned automatically. Hence, an explicitreturn
is only necessary to exit a function early.=> (defn f [x] (setv y 10) (+ x y)) => (f 4) 14
To get Python’s behavior of returning
None
when execution reaches the end of a function, putNone
there yourself.=> (defn f [x] (setv y 10) (+ x y) None) => (print (f 4)) None
- (cut coll [start None] [stop None] [step None)¶
cut
can be used to take a subset of a list and create a new list from it. The form takes at least one parameter specifying the list to cut. Two optional parameters can be used to give the start and end position of the subset. If only one is given, it is taken as thestop
value. The third optional parameter is used to control the step stride between the elements.cut
follows the same rules as its Python counterpart. Negative indices are counted starting from the end of the list. Some example usage:Examples
=> (setv collection (range 10)) => (cut collection) [0 1 2 3 4 5 6 7 8 9] => (cut collection 5) [0 1 2 3 4] => (cut collection 2 8) [2 3 4 5 6 7] => (cut collection 2 8 2) [2 4 6] => (cut collection -4 -2) [6 7]
- (raise [exception None])¶
The
raise
form can be used to raise anException
at runtime. Example usage:Examples
(raise) ; re-rase the last exception (raise IOError) ; raise an IOError (raise (IOError "foobar")) ; raise an IOError("foobar")
raise
can accept a single argument (anException
class or instance) or no arguments to re-raise the lastException
.
- (try #* body)¶
The
try
form is used to catch exceptions (except
) and run cleanup actions (finally
).Examples
(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")))
The first argument of
try
is its body, which can contain one or more forms. Then comes any number ofexcept
clauses, then optionally anelse
clause, then optionally afinally
clause. If an exception is raised with a matchingexcept
clause during the execution of the body, thatexcept
clause will be executed. If no exceptions are raised, theelse
clause is executed. Thefinally
clause will be executed last regardless of whether an exception was raised.The return value of
try
is the last form of theexcept
clause that was run, or the last form ofelse
if no exception was raised, or thetry
body if there is noelse
clause.
- (unpack-iterable)¶
- (unpack-mapping)¶
(Also known as the splat operator, star operator, argument expansion, argument explosion, argument gathering, and varargs, among others…)
unpack-iterable
andunpack-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#*
, andunpack-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]
- (unquote symbol)¶
Within a quasiquoted form,
unquote
forces evaluation of a symbol.unquote
is aliased to the tilde (~
) symbol.=> (setv nickname "Cuddles") => (quasiquote (= nickname (unquote nickname))) '(= nickname "Cuddles") => `(= nickname ~nickname) '(= nickname "Cuddles")
- (unquote-splice symbol)¶
unquote-splice
forces the evaluation of a symbol within a quasiquoted form, much likeunquote
.unquote-splice
can be used when the symbol being unquoted contains an iterable value, as it “splices” that iterable into the quasiquoted form.unquote-splice
can also be used when the value evaluates to a false value such asNone
,False
, or0
, in which case the value is treated as an empty list and thus does not splice anything into the form.unquote-splice
is aliased to the~@
syntax.=> (setv nums [1 2 3 4]) => (quasiquote (+ (unquote-splice nums))) '(+ 1 2 3 4) => `(+ ~@nums) '(+ 1 2 3 4) => `[1 2 ~@(if (< (get nums 0) 0) nums)] '[1 2]
Here, the last example evaluates to
('+' 1 2)
, since the condition(< (nth nums 0) 0)
isFalse
, which makes thisif
expression evaluate toNone
, because theif
expression here does not have an else clause.unquote-splice
then evaluates this as an empty value, leaving no effects on the list it is enclosed in, therefore resulting in('+' 1 2)
.
- (while condition #* body)¶
while
compiles to awhile
statement. It is used to execute a set of forms as long as a condition is met. The first argument towhile
is the condition, and any remaining forms constitute the body. The following example will output “Hello world!” to the screen indefinitely:(while True (print "Hello world!"))
The last form of a
while
loop can be anelse
clause, which is executed after the loop terminates, unless it exited abnormally (e.g., withbreak
). 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
orcontinue
form in the condition of awhile
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 awhile
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
- (with #* args)¶
Wrap execution of body within a context manager given as bracket args.
with
is used to wrap the execution of a block within a context manager. The context manager can then set up the local system and tear it down in a controlled manner. The archetypical example of usingwith
is when processing files. If only a single expression is supplied, or the argument is _, then no variable is bound to the expression, as shown below.- Examples:
=> (with [arg (expr)] block) => (with [(expr)] block) => (with [arg1 (expr1) _ (expr2) arg3 (expr3)] block)
The following example will open the
NEWS
file and print its content to the screen. The file is automatically closed after it has been processed:=> (with [f (open \"NEWS\")] (print (.read f)))
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 returnsNone
. So, the previous example could also be written:=> (print (with [f (open \"NEWS\")] (.read f)))
- (with/a #* args)¶
Wrap execution of body within a context manager given as bracket args.
with/a
behaves likewith
, but is used to wrap the execution of a block within an asynchronous context manager. The context manager can then set up the local system and tear it down in a controlled manner asynchronously. Examples:- ::
=> (with/a [arg (expr)] block) => (with/a [(expr)] block) => (with/a [_ (expr) arg (expr) _ (expr)] block)
Note
with/a
returns the value of its last form, unless it suppresses an exception (because the context manager’s__aexit__
method returned true), in which case it returnsNone
.
- (yield object)¶
yield
is used to create a generator object that returns one or more values. The generator is iterable and therefore can be used in loops, list comprehensions and other similar constructs.The function
random-numbers
shows how generators can be used to generate infinite series without consuming infinite amount of memory.Examples
=> (defn multiply [bases coefficients] ... (for [#(base coefficient) (zip bases coefficients)] ... (yield (* base coefficient)))) => (multiply (range 5) (range 5)) <generator object multiply at 0x978d8ec> => (list (multiply (range 10) (range 10))) [0 1 4 9 16 25 36 49 64 81] => (import random) => (defn random-numbers [low high] ... (while True (yield (.randint random low high)))) => (list (take 15 (random-numbers 1 50))) [7 41 6 22 32 17 5 38 18 38 17 14 23 23 19]
- (yield-from object)¶
New in version 0.9.13.
yield-from
is used to call a subgenerator. This is useful if you want your coroutine to be able to delegate its processes to another coroutine, say, if using something fancy like asyncio.
- macro(hy.core.macros.cond #* args)¶
Shorthand for a nested sequence of
if
forms, like anif
-elif
-else
ladder in Python. Syntax such as(cond condition1 result1 condition2 result2)
is equivalent to
(if condition1 result1 (if condition2 result2 None))
Notice that
None
is returned when no conditions match; useTrue
as the final condition to change the fallback result. Usedo
to execute several forms as part of a single condition or result.With no arguments,
cond
returnsNone
. With an odd number of arguments,cond
raises an error.
- macro(hy.core.macros.defreader key #* body)¶
Define a new reader macro.
Reader macros are expanded at read time and allow you to modify the behavior of the Hy reader. Access to the currently instantiated HyReader is available in the
body
as&reader
. SeeHyReader
and its base classReader
for details regarding the available processing methods.Reader macro names can be any symbol that does not start with a
^
and are callable by prefixing the name with a#
. i.e.(defreader upper ...)
is called with#upper
.Examples
The following is a primitive example of a reader macro that adds Python’s colon
:
slice sugar into Hy:=> (defreader slice ... (defn parse-node [] ... (let [node (when (!= ":" (.peekc &reader)) ... (.parse-one-form &reader))] ... (if (= node '...) 'Ellipse node))) ... ... (with [(&reader.end-identifier ":")] ... (let [nodes []] ... (&reader.slurp-space) ... (nodes.append (parse-node)) ... (while (&reader.peek-and-getc ":") ... (nodes.append (parse-node))) ... ... `(slice ~@nodes)))) => (setv an-index 42) => #slice a:(+ 1 2):"column" (slice 42 3 column)
See the reader macros docs for more detailed information on how reader macros work and are defined.
- macro(hy.core.macros.delmacro #* names)¶
Delete a macro(s) from the current module
=> (require a-module [some-macro]) => (some-macro) 1 => (delmacro some-macro) => (some-macro) Traceback (most recent call last): File "<string>", line 1, in <module> (some-macro) NameError: name 'some_macro' is not defined => (delmacro some-macro) Traceback (most recent call last): File "<string>", line 1, in <module> (delmacro some-macro) NameError: macro 'some-macro' is not defined
- macro(hy.core.macros.doc symbol)¶
macro documentation
Gets help for a macro function available in this module. Use
require
to make other macros available.Use
(help foo)
instead for help with runtime objects.
- macro(hy.core.macros.export #* args)¶
A convenience macro for defining
__all__
and_hy_export_macros
, which control which Python objects and macros (respectively) are collected by*
imports inimport
andrequire
(respectively).export
allows you to provide the names as symbols instead of strings, and it callshy.mangle
for you on each name.The syntax is
(export objects macros)
, whereobjects
refers to Python objects andmacros
to macros. Keyword arguments are allowed. For example,(export :objects [my-fun MyClass] :macros [my-macro])
exports the function
my-fun
, the classMyClass
, and the macromy-macro
.
- macro(hy.core.macros.when test #* body)¶
Shorthand for
(if test (do …) None)
. Seeif
. For a logically negated version, see Hyrule’sunless
.(when panic (log.write panic) (print "Process returned:" panic.msg) (return panic))
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
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¶
The hy
module is auto imported into every Hy module and provides convient access to
the following methods
- (hy.read stream filename reader)¶
Like
hy.read-many
, but only one form is read, and shebangs are forbidden. The model corresponding to this specific form is returned, or, if there are no forms left in the stream,EOFError
is raised.stream.pos
is left where it was immediately after the form.
- (hy.read-many stream [filename <string>] reader [skip-shebang False])¶
Parse all the Hy source code in
stream
, which should be a textual file-like object or a string.filename
, if provided, is used in error messages. If noreader
is provided, a newhy.reader.hy_reader.HyReader
object is created. Ifskip_shebang
is true and a shebang line is present, it’s detected and discarded first.Return a value of type
hy.models.Lazy
. If you want to evaluate this, be careful to allow evaluating each model before reading the next, as in(hy.eval (hy.read-many o))
. By contrast, forcing all the code to be read before evaluating any of it, as in(hy.eval `(do [~@(hy.read-many o)]))
, will yield the wrong result if one form defines a reader macro that’s later used in the same stream to produce new forms.Warning
Thanks to reader macros, reading can execute arbitrary code. Don’t read untrusted input.
- (hy.eval hytree locals module ast-callback compiler filename source [import-stdlib True])¶
Evaluates a quoted expression and returns the value.
If you’re evaluating hand-crafted AST trees, make sure the line numbers are set properly. Try fix_missing_locations and related functions in the Python ast library.
Examples
=> (hy.eval '(print "Hello World")) "Hello World"
If you want to evaluate a string, use
read-str
to convert it to a form first:=> (hy.eval (hy.read-str "(+ 1 1)")) 2
- Parameters
hytree (Object) – The Hy AST object to evaluate.
locals (Optional[dict]) – Local environment in which to evaluate the Hy tree. Defaults to the calling frame.
module (Optional[Union[str, types.ModuleType]]) – Module, or name of the module, to which the Hy tree is assigned and the global values are taken. The module associated with compiler takes priority over this value. When neither module nor compiler is specified, the calling frame’s module is used.
ast_callback (Optional[Callable]) – A callback that is passed the Hy compiled tree and resulting expression object, in that order, after compilation but before evaluation.
compiler (Optional[HyASTCompiler]) – An existing Hy compiler to use for compilation. Also serves as the module value when given.
filename (Optional[str]) – The filename corresponding to the source for tree. This will be overridden by the filename field of tree, if any; otherwise, it defaults to “<string>”. When compiler is given, its filename field value is always used.
source (Optional[str]) – A string containing the source code for tree. This will be overridden by the source field of tree, if any; otherwise, if None, an attempt will be made to obtain it from the module given by module. When compiler is given, its source field value is always used.
- Returns
Result of evaluating the Hy compiled tree.
- Return type
Any
- (hy.repr obj)¶
This function is Hy’s equivalent of Python’s built-in
repr
. It returns a string representing the input object in Hy syntax.Like
repr
in Python,hy.repr
can round-trip many kinds of values. Round-tripping implies that given an objectx
,(hy.eval (hy.read-str (hy.repr x)))
returnsx
, or at least a value that’s equal tox
.Examples
=> hy.repr [1 2 3]) "[1 2 3]" => (repr [1 2 3]) "[1, 2, 3]"
- (hy.repr-register types f placeholder)¶
hy.repr-register
lets you set the function thathy.repr
calls to represent a type.Examples
=> (hy.repr-register the-type fun) => (defclass C) => (hy.repr-register C (fn [x] "cuddles")) => (hy.repr [1 (C) 2]) "[1 cuddles 2]" If the type of an object passed to ``hy.repr`` doesn't have a registered function, ``hy.repr`` falls back on ``repr``. Registered functions often call ``hy.repr`` themselves. ``hy.repr`` will automatically detect self-references, even deeply nested ones, and output ``"..."`` for them instead of calling the usual registered function. To use a placeholder other than ``"..."``, pass a string of your choice to the keyword argument ``:placeholder`` of ``hy.repr-register``. => (defclass Container [object] ... (defn __init__ (fn [self value] ... (setv self.value value)))) => (hy.repr-register Container :placeholder "HY THERE" (fn [x] ... (+ "(Container " (hy.repr x.value) ")"))) => (setv container (Container 5)) => (setv container.value container) => (print (hy.repr container)) '(Container HY THERE)'
- (hy.mangle s)¶
Stringify the argument and convert it to a valid Python identifier according to Hy’s mangling rules.
If the argument is already both legal as a Python identifier and normalized according to Unicode normalization form KC (NFKC), it will be returned unchanged. Thus,
mangle
is idempotent.Examples
=> (hy.mangle 'foo-bar) "foo_bar" => (hy.mangle 'foo-bar?) "is_foo_bar" => (hy.mangle '*) "hyx_XasteriskX" => (hy.mangle '_foo/a?) "_hyx_is_fooXsolidusXa" => (hy.mangle '-->) "hyx_XhyphenHminusX_XgreaterHthan_signX" => (hy.mangle '<--) "hyx_XlessHthan_signX__"
- (hy.unmangle s)¶
Stringify the argument and try to convert it to a pretty unmangled form. See Hy’s mangling rules.
Unmangling may not round-trip, because different Hy symbol names can mangle to the same Python identifier. In particular, Python itself already considers distinct strings that have the same normalized form (according to NFKC), such as
hello
and𝔥𝔢𝔩𝔩𝔬
, to be the same identifier.Examples
=> (hy.unmangle 'foo_bar) "foo-bar" => (hy.unmangle 'is_foo_bar) "foo-bar?" => (hy.unmangle 'hyx_XasteriskX) "*" => (hy.unmangle '_hyx_is_fooXsolidusXa) "_foo/a?" => (hy.unmangle 'hyx_XhyphenHminusX_XgreaterHthan_signX) "-->" => (hy.unmangle 'hyx_XlessHthan_signX__) "<--" => (hy.unmangle '__dunder_name__) "__dunder-name__"
- (hy.disassemble tree [codegen False])¶
Return the python AST for a quoted Hy tree as a string.
If the second argument codegen is true, generate python code instead.
New in version 0.10.0.
Dump the Python AST for given Hy tree to standard output. If codegen is
True
, the function prints Python code instead.Examples
=> (hy.disassemble '(print "Hello World!")) Module( body=[ Expr(value=Call(func=Name(id='print'), args=[Str(s='Hello World!')], keywords=[], starargs=None, kwargs=None))])
=> (hy.disassemble '(print "Hello World!") True) print('Hello World!')
- (hy.macroexpand form [result-ok False])¶
Return the full macro expansion of form.
New in version 0.10.0.
Examples
=> (require hyrule [->]) => (hy.macroexpand '(-> (a b) (x y))) '(x (a b) y) => (hy.macroexpand '(-> (a b) (-> (c d) (e f)))) '(e (c (a b) d) f)
- (hy.macroexpand-1 form)¶
Return the single step macro expansion of form.
New in version 0.10.0.
Examples
=> (require hyrule [->]) => (hy.macroexpand-1 '(-> (a b) (-> (c d) (e f)))) '(-> (a b) (c d) (e f))
- (hy.gensym [g G])¶
Generate a symbol with a unique name. The argument will be included in the generated symbol, as an aid to debugging. Typically one calls
hy.gensym
without an argument.New in version 0.9.12.
See also
Section Using gensym for Safer Macros
The below example uses the return value of
f
twice but calls it only once, and useshy.gensym
for the temporary variable to avoid collisions with any other variable names.(defmacro selfadd [x] (setv g (hy.gensym)) `(do (setv ~g ~x) (+ ~g ~g))) (defn f [] (print "This is only executed once.") 4) (print (selfadd (f)))
- (hy.as-model x)¶
Recursively promote an object
x
into its canonical model form.When creating macros its possible to return non-Hy model objects or even create an expression with non-Hy model elements:
=> (defmacro hello [] ... "world!") => (defmacro print-inc [a] ... `(print ~(+ a 1))) => (print-inc 1) 2 ; in this case the unquote form (+ 1 1) would splice the literal ; integer ``2`` into the print statement, *not* the model representation ; ``(hy.model.Integer 2)``
This is perfectly fine, because Hy autoboxes these literal values into their respective model forms at compilation time.
The one case where this distinction between the spliced composit form and the canonical model tree representation matters, is when comparing some spliced model tree with another known tree:
=> (= `(print ~(+ 1 1)) '(print 2)) False ; False because the literal int ``2`` in the spliced form is not ; equal to the ``(hy.model.Integer 2)`` value in the known form. => (= (hy.as-model `(print ~(+ 1 1)) '(print 2))) True ; True because ``as-model`` has walked the expression and promoted ; the literal int ``2`` to its model for ``(hy.model.Integer 2)``
Reader Macros¶
Like regular macros, reader macros should return a Hy form that will then be
passed to the compiler for execution. Reader macros access the Hy reader using
the &reader
name. It gives access to all of the text- and form-parsing logic
that Hy uses to parse itself. See HyReader
and
its base class Reader
for details regarding
the available processing methods.
- class hy.reader.hy_reader.HyReader[source]¶
A modular reader for Hy source.
- fill_pos(model, start)[source]¶
Attach line/col information to a model.
Sets the end location of model to the current cursor position.
- Parameters
model (hy.models.Object) – model to set line/col info for.
start (tuple[int, int]) – (line, column) tuple indicating the start location to assign to model.
- parse(stream, filename=None)[source]¶
Yields all hy.models.Object’s in source
Additionally exposes self as
hy.&reader
during read/compile time.- Parameters
source – Hy source to be parsed.
filename (str | None) – Filename to use for error messages. If None then previously set filename is used.
- parse_forms_until(closer)[source]¶
Yields hy.models.Object’s until character closer is seen.
Useful for reading a sequence such as s-exprs or lists.
- class hy.reader.reader.Reader[source]¶
A reader base class for reading input character-by-character. Only for use as a base class; cannot be instantiated directly.
See class
HyReader
for an example of creating a reader class.- pos¶
Read-only (line, column) tuple indicating the current cursor position of the source being read.
- chars(eof_ok=False)[source]¶
Iterator for the character stream.
Consumes characters as they are produced.
- Parameters
eof_ok (bool) – Whether or not it’s okay to hit the end of the file while consuming the iterator. Defaults to False
- Yields
str – The next character in source.
- Raises
PrematureEndOfInput – if eof_ok is False and the iterator hits the end of source
- dispatch(tag)[source]¶
Call the handler for the tag.
- Parameters
tag (str) – Reader macro dispatch key.
- Returns
Model returned by the reader macro defined for tag.
- Return type
hy.models.Object | None
- end_identifier(character)[source]¶
Temporarily add a new character to the
ends_ident
set.
- getc()[source]¶
Get one character from the stream, consuming it.
This function does the bookkeeping for position data, so it’s important that any character consumption go through this function.
- peek_and_getc(target)[source]¶
Peek one character and check if it’s equal to target.
Only consumes the peeked character if it is equal to target
- Returns
Whether or not the next character in the stream is equal to target.
- Return type
- peeking(eof_ok=False)[source]¶
Iterate over character stream without consuming any characters.
Useful for looking multiple characters ahead.
- Parameters
eof_ok (bool) – Whether or not it is okay to hit the end of the file while peeking. Defaults to False
- Yields
str – The next character in source.
- Raises
PrematureEndOfInput – if eof_ok is False and the iterator hits the end of source
- read_ident(just_peeking=False)[source]¶
Read characters until we hit something in
ends_ident
.- Parameters
just_peeking – Whether or not to consume characters while peeking. Defaults to False.
- Returns
The identifier read.
- Return type
Python Operators¶
Python provides various binary and unary operators. These are usually invoked in Hy using core macros of
the same name: for example, (+ 1 2)
calls the core macro named
+
, which uses Python’s addition operator. An exception to the names
being the same is that Python’s ==
is called =
in Hy.
By importing from the module hy.pyops
(typically with a star import,
as in (import hy.pyops *)
), you can also use these operators as
functions. Functions are first-class objects, so you can say things like
(map - xs)
to negate all the numbers in the list xs
. Since
macros shadow functions, forms like (- 1 2)
will still call the
macro instead of the function.
The functions in hy.pyops
have the same semantics as their macro
equivalents, with one exception: functions can’t short-circuit, so the
functions for the logical operators, such as and
, unconditionally
evaluate all arguments.
- (hy.pyops.!= a1 a2 #* a-rest)¶
The inequality operator. Its effect can be defined by the equivalent Python:
(!= x y)
→x != y
(!= a1 a2 … an)
→a1 != a2 != … != an
- (hy.pyops.% x y)¶
The modulus operator. Its effect can be defined by the equivalent Python:
(% x y)
→x % y
- (hy.pyops.& a1 #* a-rest)¶
The bitwise AND operator. Its effect can be defined by the equivalent Python:
(& x)
→x
(& x y)
→x & y
(& a1 a2 … an)
→a1 & a2 & … & an
- (hy.pyops.* #* args)¶
The multiplication operator. Its effect can be defined by the equivalent Python:
(*)
→0
(* x)
→x
(* x y)
→x * y
(* a1 a2 … an)
→a1 * a2 * … * an
- (hy.pyops.** a1 a2 #* a-rest)¶
The exponentiation operator. Its effect can be defined by the equivalent Python:
(** x y)
→x ** y
(** a1 a2 … an)
→a1 ** a2 ** … ** an
- (hy.pyops.+ #* args)¶
The addition operator. Its effect can be defined by the equivalent Python:
(+)
→0
(+ x)
→+x
(+ x y)
→x + y
(+ a1 a2 … an)
→a1 + a2 + … + an
- (hy.pyops.- a1 #* a-rest)¶
The subtraction operator. Its effect can be defined by the equivalent Python:
(- x)
→-x
(- x y)
→x - y
(- a1 a2 … an)
→a1 - a2 - … - an
- (hy.pyops./ a1 #* a-rest)¶
The division operator. Its effect can be defined by the equivalent Python:
(/ x)
→1 / x
(/ x y)
→x / y
(/ a1 a2 … an)
→a1 / a2 / … / an
- (hy.pyops.// a1 a2 #* a-rest)¶
The floor division operator. Its effect can be defined by the equivalent Python:
(// x y)
→x // y
(// a1 a2 … an)
→a1 // a2 // … // an
- (hy.pyops.< a1 #* a-rest)¶
The less-than operator. Its effect can be defined by the equivalent Python:
(< x)
→True
(< x y)
→x < y
(< a1 a2 … an)
→a1 < a2 < … < an
- (hy.pyops.<< a1 a2 #* a-rest)¶
The left shift operator. Its effect can be defined by the equivalent Python:
(<< x y)
→x << y
(<< a1 a2 … an)
→a1 << a2 << … << an
- (hy.pyops.<= a1 #* a-rest)¶
The less-than-or-equal-to operator. Its effect can be defined by the equivalent Python:
(<= x)
→True
(<= x y)
→x <= y
(<= a1 a2 … an)
→a1 <= a2 <= … <= an
- (hy.pyops.= a1 #* a-rest)¶
The equality operator. Its effect can be defined by the equivalent Python:
(= x)
→True
(= x y)
→x == y
(= a1 a2 … an)
→a1 == a2 == … == an
- (hy.pyops.> a1 #* a-rest)¶
The greater-than operator. Its effect can be defined by the equivalent Python:
(> x)
→True
(> x y)
→x > y
(> a1 a2 … an)
→a1 > a2 > … > an
- (hy.pyops.>= a1 #* a-rest)¶
The greater-than-or-equal-to operator. Its effect can be defined by the equivalent Python:
(>= x)
→True
(>= x y)
→x >= y
(>= a1 a2 … an)
→a1 >= a2 >= … >= an
- (hy.pyops.>> a1 a2 #* a-rest)¶
The right shift operator. Its effect can be defined by the equivalent Python:
(>> x y)
→x >> y
(>> a1 a2 … an)
→a1 >> a2 >> … >> an
- (hy.pyops.@ a1 #* a-rest)¶
The matrix multiplication operator. Its effect can be defined by the equivalent Python:
(@ x y)
→x @ y
(@ a1 a2 … an)
→a1 @ a2 @ … @ an
- (hy.pyops.[x y])¶
The bitwise XOR operator. Its effect can be defined by the equivalent Python:
(^ x y)
→x ^ y
- (hy.pyops.and #* args)¶
The logical conjuction operator. Its effect can be defined by the equivalent Python:
(and)
→True
(and x)
→x
(and x y)
→x and y
(and a1 a2 … an)
→a1 and a2 and … and an
- (hy.pyops.comp-op op a1 a-rest)¶
Helper for shadow comparison operators
- (hy.pyops.get coll key1 #* keys)¶
Access item in coll indexed by key1, with optional keys nested-access.
get
is used to access single elements in collections.get
takes at least two parameters: the data structure and the index or key of the item. It will then return the corresponding value from the collection. If multiple index or key values are provided, they are used to access successive elements in a nested structure.Note
get
raises a KeyError if a dictionary is queried for a non-existing key.Note
get
raises an IndexError if a list or a tuple is queried for an index that is out of bounds.Examples
=> (do ... (setv animals {"dog" "bark" "cat" "meow"} ... numbers #("zero" "one" "two" "three") ... nested [0 1 ["a" "b" "c"] 3 4]) ... (print (get animals "dog")) ... (print (get numbers 2)) ... (print (get nested 2 1)) bark two b
- (hy.pyops.in a1 a2 #* a-rest)¶
The membership test operator. Its effect can be defined by the equivalent Python:
(in x y)
→x in y
(in a1 a2 … an)
→a1 in a2 in … in an
- (hy.pyops.is a1 #* a-rest)¶
The identicality test operator. Its effect can be defined by the equivalent Python:
(is x)
→True
(is x y)
→x is y
(is a1 a2 … an)
→a1 is a2 is … is an
- (hy.pyops.not-in a1 a2 #* a-rest)¶
The negated membership test operator. Its effect can be defined by the equivalent Python:
(not-in x y)
→x not in y
(not-in a1 a2 … an)
→a1 not in a2 not in … not in an
- (hy.pyops.not? a1 a2 #* a-rest)¶
The negated identicality test operator. Its effect can be defined by the equivalent Python:
(is-not x y)
→x is not y
(is-not a1 a2 … an)
→a1 is not a2 is not … is not an
- (hy.pyops.or #* args)¶
The logical disjunction operator. Its effect can be defined by the equivalent Python:
(or)
→None
(or x)
→x
(or x y)
→x or y
(or a1 a2 … an)
→a1 or a2 or … or an
- (hy.pyops.reduce)¶
reduce(function, sequence[, initial]) -> value
Apply a function of two arguments cumulatively to the items of a sequence, from left to right, so as to reduce the sequence to a single value. For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates ((((1+2)+3)+4)+5). If initial is present, it is placed before the items of the sequence in the calculation, and serves as a default when the sequence is empty.
- (hy.pyops.| #* args)¶
The bitwise OR operator. Its effect can be defined by the equivalent Python:
(|)
→0
(| x)
→x
(| x y)
→x | y
(| a1 a2 … an)
→a1 | a2 | … | an
- (hy.pyops.~ x)¶
The bitwise NOT operator. Its effect can be defined by the equivalent Python:
(~ x)
→~x
Reserved¶
- (hy.reserved.macros)¶
Return a frozenset of Hy’s core macro names.
- (hy.reserved.names)¶
Return a frozenset of reserved symbol names.
The result of the first call is cached.
The output includes all of Hy’s core functions and macros, plus all Python reserved words. All names are in unmangled form (e.g.,
not-in
rather thannot_in
).Examples
=> (import hy.extra.reserved) => (in "defclass" (hy.extra.reserved.names)) True