Hy

Личный сайт Go-разработчика из Казани

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