Hy is a Lisp dialect built on top of Python. This is achieved by converting Hy code to Python’s abstract syntax tree (AST). This allows Hy to call native Python code or Python to call native Hy code as well
1; Semicolon comments, like other Lisps
2
3;; S-expression basics
4; Lisp programs are made of symbolic expressions or sexps which
5; resemble
6(some-function args)
7; now the quintessential hello world
8(print "hello world")
9
10;; Simple data types
11; All simple data types are the same as their Python counterparts
1242 ; => 42
133.14 ; => 3.14
14True ; => True
154+10j ; => (4+10j) a complex number
16
17; lets start with some simple arithmetic
18(+ 4 1) ;=> 5
19; the operator is applied to all arguments, like other Lisps
20(+ 4 1 2 3) ;=> 10
21(- 2 1) ;=> 1
22(* 4 2) ;=> 8
23(/ 4 1) ;=> 4
24(% 4 2) ;=> 0 the modulo operator
25; power is represented by the ** operator, like Python
26(** 3 2) ;=> 9
27; nesting forms will do the expected thing
28(+ 2 (* 4 2)) ;=> 10
29; also logical operators and or not and equal to etc. work as expected
30(= 5 4) ;=> False
31(not (= 5 4)) ;=> True
32
33;; Variables
34; variables are set using setv, variable names can use utf-8 except
35; for ()[]{}",'`;#|
36(setv a 42)
37(setv π 3.14159)
38(def *foo* 42)
39;; Other container data types
40; strings, lists, tuples & dicts
41; these are exactly same as Python's container types
42"hello world" ;=> "hello world"
43; string operations work similar to Python
44(+ "hello " "world") ;=> "hello world"
45; lists are created using [], indexing starts at 0
46(setv mylist [1 2 3 4])
47; tuples are immutable data structures
48(setv mytuple (, 1 2))
49; dictionaries are key value pairs
50(setv dict1 {"key1" 42 "key2" 21})
51; :name can be used to define keywords in Hy which can be used for keys
52(setv dict2 {:key1 41 :key2 20})
53; use `get' to get the element at an index/key
54(get mylist 1) ;=> 2
55(get dict1 "key1") ;=> 42
56; Alternatively if keywords were used they can be called directly
57(:key1 dict2) ;=> 41
58
59;; Functions and other program constructs
60; functions are defined using defn, the last sexp is returned by default
61(defn greet [name]
62 "A simple greeting" ; an optional docstring
63 (print "hello " name))
64
65(greet "bilbo") ;=> "hello bilbo"
66
67; functions can take optional arguments as well as keyword arguments
68(defn foolists [arg1 &optional [arg2 2]]
69 [arg1 arg2])
70
71(foolists 3) ;=> [3 2]
72(foolists 10 3) ;=> [10 3]
73
74; you can use rest arguments and kwargs too:
75(defn something-fancy [wow &rest descriptions &kwargs props]
76 (print "Look at" wow)
77 (print "It's" descriptions)
78 (print "And it also has:" props))
79
80(something-fancy "My horse" "amazing" :mane "spectacular")
81
82; you use apply instead of the splat operators:
83(apply something-fancy ["My horse" "amazing"] { "mane" "spectacular" })
84
85; anonymous functions are created using `fn' or `lambda' constructs
86; which are similar to `defn'
87(map (fn [x] (* x x)) [1 2 3 4]) ;=> [1 4 9 16]
88
89;; Sequence operations
90; Hy has some builtin utils for sequence operations etc.
91; retrieve the first element using `first' or `car'
92(setv mylist [1 2 3 4])
93(setv mydict {"a" 1 "b" 2})
94(first mylist) ;=> 1
95
96; slice lists using cut
97(cut mylist 1 3) ;=> [2 3]
98
99; get elements from a list or dict using `get'
100(get mylist 1) ;=> 2
101(get mydict "b") ;=> 2
102; list indexing starts from 0, same as Python
103; assoc can set elements at keys/indexes
104(assoc mylist 2 10) ; makes mylist [1 2 10 4]
105(assoc mydict "c" 3) ; makes mydict {"a" 1 "b" 2 "c" 3}
106; there are a whole lot of other core functions which makes working with
107; sequences fun
108
109;; Python interop
110;; import works just like in Python
111(import datetime)
112(import functools [partial reduce]) ; imports partial and reduce from functools
113(import matplotlib.pyplot :as plt) ; imports foo as bar
114; all builtin Python methods etc. are accessible from Hy
115; a.foo(arg) is called as (.foo a arg)
116(.split (.strip "hello world ")) ;=> ["hello" "world"]
117
118; there is a shortcut for executing multiple functions on a value called the
119; "threading macro", denoted by an arrow:
120(-> "hello world " (.strip) (.split)) ;=> ["hello" "world]
121; the arrow passes the value along the calls as the first argument, for instance:
122(-> 4 (* 3) (+ 2))
123; is the same as:
124(+ (* 4 3) 2)
125
126; there is also a "threading tail macro", which instead passes the value as the
127; second argument. compare:
128(-> 4 (- 2) (+ 1)) ;=> 3
129(+ (- 4 2) 1) ;=> 3
130; to:
131(->> 4 (- 2) (+ 1)) ;=> -1
132(+ 1 (- 2 4)) ;=> -1
133
134;; Conditionals
135; (if condition (body-if-true) (body-if-false)
136(if (= passcode "moria")
137 (print "welcome")
138 (print "Speak friend, and Enter!"))
139
140; nest multiple if else if clauses with cond
141(cond
142 (= someval 42) (print "Life, universe and everything else!")
143 (> someval 42) (print "val too large")
144 (< someval 42) (print "val too small"))
145
146; group statements with do, these are executed sequentially
147; forms like defn have an implicit do
148(do
149 (setv someval 10)
150 (print "someval is set to " someval)) ;=> 10
151
152; create lexical bindings with `let', all variables defined thusly
153; have local scope
154(let [nemesis {"superman" "lex luther"
155 "sherlock" "moriarty"
156 "seinfeld" "newman"}]
157 (for [[h v] (.items nemesis)]
158 (print (.format "{0}'s nemesis was {1}" h v))))
159
160;; Classes
161; classes are defined in the following way
162(defclass Wizard [object]
163 (defn __init__ [self spell]
164 (setv self.spell spell))
165
166 (defn get-spell [self]
167 self.spell))
Further Reading ¶
This tutorial is just a basic introduction to Hy/Lisp/Python.
Hy docs are here: https://hylang.org/hy/doc
Hy’s GitHub repo: https://github.com/hylang/hy
On freenode IRC #hy
, twitter hashtag #hylang