Hy Core

Core Functions

butlast

Usage: (butlast coll)

Returns an iterator of all but the last item in coll.

=> (list (butlast (range 10)))
[0, 1, 2, 3, 4, 5, 6, 7, 8]

=> (list (butlast [1]))
[]

=> (list (butlast []))
[]

=> (list (take 5 (butlast (count 10))))
[10, 11, 12, 13, 14]

coll?

New in version 0.10.0.

Usage: (coll? x)

Returns True if x is iterable and not a string.

=> (coll? [1 2 3 4])
True

=> (coll? {"a" 1 "b" 2})
True

=> (coll? "abc")
False

comp

Usage: (comp f g)

Compose zero or more functions into a new function. The new function will chain the given functions together, so ((comp g f) x) is equivalent to (g (f x)). Called without arguments, comp returns identity.

=> (def example (comp str +))
=> (example 1 2 3)
"6"

=> (def simple (comp))
=> (simple "hello")
"hello"

complement

New in version 0.12.0.

Usage: (complement f)

Returns a new function that returns the same thing as f, but logically inverted. So, ((complement f) x) is equivalent to (not (f x)).

=> (def inverse (complement identity))
=> (inverse True)
False
=> (inverse 1)
False
=> (inverse False)
True

cons

New in version 0.10.0.

Usage: (cons a b)

Returns a fresh cons cell with car a and cdr b.

=> (setv a (cons 'hd 'tl))

=> (= 'hd (get a 0))
True

=> (= 'tl (cut a 1))
True

cons?

New in version 0.10.0.

Usage: (cons? foo)

Checks whether foo is a cons cell.

=> (setv a (cons 'hd 'tl))

=> (cons? a)
True

=> (cons? None)
False

=> (cons? [1 2 3])
False

constantly

New in version 0.12.0.

Usage (constantly 42)

Create a new function that always returns the given value, regardless of the arguments given to it.

=> (def answer (constantly 42))
=> (answer)
42
=> (answer 1 2 3)
42
=> (answer 1 :foo 2)
42

dec

Usage: (dec x)

Returns one less than x. Equivalent to (- x 1). Raises TypeError if (not (numeric? x)).

=> (dec 3)
2

=> (dec 0)
-1

=> (dec 12.3)
11.3

disassemble

New in version 0.10.0.

Usage: (disassemble tree &optional [codegen false])

Dump the Python AST for given Hy tree to standard output. If codegen is True, the function prints Python code instead.

=> (disassemble '(print "Hello World!"))
Module(
 body=[
     Expr(value=Call(func=Name(id='print'), args=[Str(s='Hello World!')], keywords=[], starargs=None, kwargs=None))])

=> (disassemble '(print "Hello World!") True)
print('Hello World!')

empty?

Usage: (empty? coll)

Returns True if coll is empty. Equivalent to (= 0 (len coll)).

=> (empty? [])
True

=> (empty? "")
True

=> (empty? (, 1 2))
False

every?

New in version 0.10.0.

Usage: (every? pred coll)

Returns True if (pred x) is logical true for every x in coll, otherwise False. Return True if coll is empty.

=> (every? even? [2 4 6])
True

=> (every? even? [1 3 5])
False

=> (every? even? [2 4 5])
False

=> (every? even? [])
True

float?

Usage: (float? x)

Returns True if x is a float.

=> (float? 3.2)
True

=> (float? -2)
False

fraction

Returns a Python object of type fractions.Fraction.

=> (fraction 1 2)
Fraction(1, 2)

Note that Hy has a built-in fraction literal that does the same thing:

=> 1/2
Fraction(1, 2)

even?

Usage: (even? x)

Returns True if x is even. Raises TypeError if (not (numeric? x)).

=> (even? 2)
True

=> (even? 13)
False

=> (even? 0)
True

identity

Usage: (identity x)

Returns the argument supplied to the function.

=> (identity 4)
4

=> (list (map identity [1 2 3 4]))
[1 2 3 4]

inc

Usage: (inc x)

Returns one more than x. Equivalent to (+ x 1). Raises TypeError if (not (numeric? x)).

=> (inc 3)
4

=> (inc 0)
1

=> (inc 12.3)
13.3

instance?

Usage: (instance? class x)

Returns True if x is an instance of class.

=> (instance? float 1.0)
True

=> (instance? int 7)
True

=> (instance? str (str "foo"))
True

=> (defclass TestClass [object])
=> (setv inst (TestClass))
=> (instance? TestClass inst)
True

integer?

Usage: (integer? x)

Returns True if x is an integer. For Python 2, this is either int or long. For Python 3, this is int.

=> (integer? 3)
True

=> (integer? -2.4)
False

interleave

New in version 0.10.1.

Usage: (interleave seq1 seq2 ...)

Returns an iterable of the first item in each of the sequences, then the second, etc.

=> (list (interleave (range 5) (range 100 105)))
[0, 100, 1, 101, 2, 102, 3, 103, 4, 104]

=> (list (interleave (range 1000000) "abc"))
[0, 'a', 1, 'b', 2, 'c']

interpose

New in version 0.10.1.

Usage: (interpose item seq)

Returns an iterable of the elements of the sequence separated by the item.

=> (list (interpose "!" "abcd"))
['a', '!', 'b', '!', 'c', '!', 'd']

=> (list (interpose -1 (range 5)))
[0, -1, 1, -1, 2, -1, 3, -1, 4]

iterable?

Usage: (iterable? x)

Returns True if x is iterable. Iterable objects return a new iterator when (iter x) is called. Contrast with iterator?.

=> ;; works for strings
=> (iterable? (str "abcde"))
True

=> ;; works for lists
=> (iterable? [1 2 3 4 5])
True

=> ;; works for tuples
=> (iterable? (, 1 2 3))
True

=> ;; works for dicts
=> (iterable? {:a 1 :b 2 :c 3})
True

=> ;; works for iterators/generators
=> (iterable? (repeat 3))
True

iterator?

Usage: (iterator? x)

Returns True if x is an iterator. Iterators are objects that return themselves as an iterator when (iter x) is called. Contrast with iterable?.

=> ;; doesn't work for a list
=> (iterator? [1 2 3 4 5])
False

=> ;; but we can get an iter from the list
=> (iterator? (iter [1 2 3 4 5]))
True

=> ;; doesn't work for dict
=> (iterator? {:a 1 :b 2 :c 3})
False

=> ;; create an iterator from the dict
=> (iterator? (iter {:a 1 :b 2 :c 3}))
True

juxt

New in version 0.12.0.

Usage: (juxt f &rest fs)

Return a function that applies each of the supplied functions to a single set of arguments and collects the results into a list.

=> ((juxt min max sum) (range 1 101))
[1, 100, 5050]

=> (dict (map (juxt identity ord) "abcdef"))
{'f': 102, 'd': 100, 'b': 98, 'e': 101, 'c': 99, 'a': 97}

=> ((juxt + - * /) 24 3)
[27, 21, 72, 8.0]

keyword

New in version 0.10.1.

Usage: (keyword "foo")

Create a keyword from the given value. Strings, numbers, and even objects with the __name__ magic will work.

=> (keyword "foo")
u'\ufdd0:foo'

=> (keyword 1)
u'\ufdd0:1'

keyword?

New in version 0.10.1.

Usage: (keyword? foo)

Check whether foo is a keyword.

=> (keyword? :foo)
True

=> (setv foo 1)
=> (keyword? foo)
False

list*

Usage: (list* head &rest tail)

Generates a chain of nested cons cells (a dotted list) containing the arguments. If the argument list only has one element, return it.

=> (list* 1 2 3 4)
(1 2 3 . 4)

=> (list* 1 2 3 [4])
[1, 2, 3, 4]

=> (list* 1)
1

=> (cons? (list* 1 2 3 4))
True

macroexpand

New in version 0.10.0.

Usage: (macroexpand form)

Returns the full macro expansion of form.

=> (macroexpand '(-> (a b) (x y)))
(u'x' (u'a' u'b') u'y')

=> (macroexpand '(-> (a b) (-> (c d) (e f))))
(u'e' (u'c' (u'a' u'b') u'd') u'f')

macroexpand-1

New in version 0.10.0.

Usage: (macroexpand-1 form)

Returns the single step macro expansion of form.

=> (macroexpand-1 '(-> (a b) (-> (c d) (e f))))
(u'_>' (u'a' u'b') (u'c' u'd') (u'e' u'f'))

merge-with

New in version 0.10.1.

Usage: (merge-with f &rest maps)

Returns a map that consist of the rest of the maps joined onto first. If a key occurs in more than one map, the mapping(s) from the latter (left-to-right) will be combined with the mapping in the result by calling (f val-in-result val-in-latter).

=> (merge-with (fn [x y] (+ x y)) {"a" 10 "b" 20} {"a" 1 "c" 30})
{u'a': 11L, u'c': 30L, u'b': 20L}

name

New in version 0.10.1.

Usage: (name :keyword)

Convert the given value to a string. Keyword special character will be stripped. Strings will be used as is. Even objects with the __name__ magic will work.

=> (name :foo)
u'foo'

neg?

Usage: (neg? x)

Returns True if x is less than zero. Raises TypeError if (not (numeric? x)).

=> (neg? -2)
True

=> (neg? 3)
False

=> (neg? 0)
False

none?

Usage: (none? x)

Returns True if x is None.

=> (none? None)
True

=> (none? 0)
False

=> (setv x None)
=> (none? x)
True

=> ;; list.append always returns None
=> (none? (.append [1 2 3] 4))
True

nth

Usage: (nth coll n &optional [default None])

Returns the n-th item in a collection, counting from 0. Return the default value, None, if out of bounds (unless specified otherwise). Raises ValueError if n is negative.

=> (nth [1 2 4 7] 1)
2

=> (nth [1 2 4 7] 3)
7

=> (none? (nth [1 2 4 7] 5))
True

=> (nth [1 2 4 7] 5 "default")
'default'

=> (nth (take 3 (drop 2 [1 2 3 4 5 6])) 2))
5

=> (nth [1 2 4 7] -1)
Traceback (most recent call last):
  ...
ValueError: Indices for islice() must be None or an integer: 0 <= x <= sys.maxsize.

numeric?

Usage: (numeric? x)

Returns True if x is a numeric, as defined in Python's numbers.Number class.

=> (numeric? -2)
True

=> (numeric? 3.2)
True

=> (numeric? "foo")
False

odd?

Usage: (odd? x)

Returns True if x is odd. Raises TypeError if (not (numeric? x)).

=> (odd? 13)
True

=> (odd? 2)
False

=> (odd? 0)
False

partition

Usage: (partition coll [n] [step] [fillvalue])

Chunks coll into n-tuples (pairs by default).

=> (list (partition (range 10)))  ; n=2
[(, 0 1) (, 2 3) (, 4 5) (, 6 7) (, 8 9)]

The step defaults to n, but can be more to skip elements, or less for a sliding window with overlap.

=> (list (partition (range 10) 2 3))
[(, 0 1) (, 3 4) (, 6 7)]
=> (list (partition (range 5) 2 1))
[(, 0 1) (, 1 2) (, 2 3) (, 3 4)])

The remainder, if any, is not included unless a fillvalue is specified.

=> (list (partition (range 10) 3))
[(, 0 1 2) (, 3 4 5) (, 6 7 8)]
=> (list (partition (range 10) 3 :fillvalue "x"))
[(, 0 1 2) (, 3 4 5) (, 6 7 8) (, 9 "x" "x")]

pos?

Usage: (pos? x)

Returns True if x is greater than zero. Raises TypeError if (not (numeric? x)).

=> (pos? 3)
True

=> (pos? -2)
False

=> (pos? 0)
False

second

Usage: (second coll)

Returns the second member of coll. Equivalent to (get coll 1).

=> (second [0 1 2])
1

some

New in version 0.10.0.

Usage: (some pred coll)

Returns the first logically-true value of (pred x) for any x in coll, otherwise None. Return None if coll is empty.

=> (some even? [2 4 6])
True

=> (none? (some even? [1 3 5]))
True

=> (none? (some identity [0 "" []]))
True

=> (some identity [0 "non-empty-string" []])
'non-empty-string'

=> (none? (some even? []))
True

string?

Usage: (string? x)

Returns True if x is a string.

=> (string? "foo")
True

=> (string? -2)
False

symbol?

Usage: (symbol? x)

Returns True if x is a symbol.

=> (symbol? 'foo)
True

=> (symbol? '[a b c])
False

zero?

Usage: (zero? x)

Returns True if x is zero.

=> (zero? 3)
False

=> (zero? -2)
False

=> (zero? 0)
True

Sequence Functions

Sequence functions can either create or operate on a potentially infinite sequence without requiring the sequence be fully realized in a list or similar container. They do this by returning a Python iterator.

We can use the canonical infinite Fibonacci number generator as an example of how to use some of these functions.

(defn fib []
  (setv a 0)
  (setv b 1)
  (while True
    (yield a)
    (setv (, a b) (, b (+ a b)))))

Note the (while True ...) loop. If we run this in the REPL,

=> (fib)
<generator object fib at 0x101e642d0>

Calling the function only returns an iterator, but does no work until we consume it. Trying something like this is not recommend as the infinite loop will run until it consumes all available RAM, or in this case until I killed it.

=> (list (fib))
[1]    91474 killed     hy

To get the first 10 Fibonacci numbers, use take. Note that take also returns a generator, so I create a list from it.

=> (list (take 10 (fib)))
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

To get the Fibonacci number at index 9, (starting from 0):

=> (nth (fib) 9)
34

cycle

Usage: (cycle coll)

Returns an infinite iterator of the members of coll.

=> (list (take 7 (cycle [1 2 3])))
[1, 2, 3, 1, 2, 3, 1]

=> (list (take 2 (cycle [1 2 3])))
[1, 2]

distinct

Usage: (distinct coll)

Returns an iterator containing only the unique members in coll.

=> (list (distinct [ 1 2 3 4 3 5 2 ]))
[1, 2, 3, 4, 5]

=> (list (distinct []))
[]

=> (list (distinct (iter [ 1 2 3 4 3 5 2 ])))
[1, 2, 3, 4, 5]

drop

Usage: (drop n coll)

Returns an iterator, skipping the first n members of coll. Raises ValueError if n is negative.

=> (list (drop 2 [1 2 3 4 5]))
[3, 4, 5]

=> (list (drop 4 [1 2 3 4 5]))
[5]

=> (list (drop 0 [1 2 3 4 5]))
[1, 2, 3, 4, 5]

=> (list (drop 6 [1 2 3 4 5]))
[]

drop-last

Usage: (drop-last n coll)

Returns an iterator of all but the last n items in coll. Raises ValueError if n is negative.

=> (list (drop-last 5 (range 10 20)))
[10, 11, 12, 13, 14]

=> (list (drop-last 0 (range 5)))
[0, 1, 2, 3, 4]

=> (list (drop-last 100 (range 100)))
[]

=> (list (take 5 (drop-last 100 (count 10))))
[10, 11, 12, 13, 14]

drop-while

Usage: (drop-while pred coll)

Returns an iterator, skipping members of coll until pred is False.

=> (list (drop-while even? [2 4 7 8 9]))
[7, 8, 9]

=> (list (drop-while numeric? [1 2 3 None "a"])))
[None, u'a']

=> (list (drop-while pos? [2 4 7 8 9]))
[]

filter

Usage: (filter pred coll)

Returns an iterator for all items in coll that pass the predicate pred.

See also remove.

=> (list (filter pos? [1 2 3 -4 5 -7]))
[1, 2, 3, 5]

=> (list (filter even? [1 2 3 -4 5 -7]))
[2, -4]

flatten

New in version 0.9.12.

Usage: (flatten coll)

Returns a single list of all the items in coll, by flattening all contained lists and/or tuples.

=> (flatten [1 2 [3 4] 5])
[1, 2, 3, 4, 5]

=> (flatten ["foo" (, 1 2) [1 [2 3] 4] "bar"])
['foo', 1, 2, 1, 2, 3, 4, 'bar']

iterate

Usage: (iterate fn x)

Returns an iterator of x, fn(x), fn(fn(x)), etc.

=> (list (take 5 (iterate inc 5)))
[5, 6, 7, 8, 9]

=> (list (take 5 (iterate (fn [x] (* x x)) 5)))
[5, 25, 625, 390625, 152587890625]

read

Usage: (read &optional [from-file eof])

Reads the next Hy expression from from-file (defaulting to sys.stdin), and can take a single byte as EOF (defaults to an empty string). Raises EOFError if from-file ends before a complete expression can be parsed.

=> (read)
(+ 2 2)
('+' 2 2)
=> (eval (read))
(+ 2 2)
4

=> (import io)
=> (def buffer (io.StringIO "(+ 2 2)\n(- 2 1)"))
=> (eval (apply read [] {"from_file" buffer}))
4
=> (eval (apply read [] {"from_file" buffer}))
1

=> ; assuming "example.hy" contains:
=> ;   (print "hello")
=> ;   (print "hyfriends!")
=> (with [f (open "example.hy")]
...   (try
...     (while True
...            (setv exp (read f))
...            (print "OHY" exp)
...            (eval exp))
...     (except [e EOFError]
...            (print "EOF!"))))
OHY ('print' 'hello')
hello
OHY ('print' 'hyfriends!')
hyfriends!
EOF!

read-str

Usage: (read-str "string")

This is essentially a wrapper around read which reads expressions from a string:

=> (read-str "(print 1)")
(u'print' 1L)
=> (eval (read-str "(print 1)"))
1
=>

remove

Usage: (remove pred coll)

Returns an iterator from coll with elements that pass the predicate, pred, removed.

See also filter.

=> (list (remove odd? [1 2 3 4 5 6 7]))
[2, 4, 6]

=> (list (remove pos? [1 2 3 4 5 6 7]))
[]

=> (list (remove neg? [1 2 3 4 5 6 7]))
[1, 2, 3, 4, 5, 6, 7]

repeat

Usage: (repeat x)

Returns an iterator (infinite) of x.

=> (list (take 6 (repeat "s")))
[u's', u's', u's', u's', u's', u's']

repeatedly

Usage: (repeatedly fn)

Returns an iterator by calling fn repeatedly.

=> (import [random [randint]])

=> (list (take 5 (repeatedly (fn [] (randint 0 10)))))
[6, 2, 0, 6, 7]

take

Usage: (take n coll)

Returns an iterator containing the first n members of coll. Raises ValueError if n is negative.

=> (list (take 3 [1 2 3 4 5]))
[1, 2, 3]

=> (list (take 4 (repeat "s")))
[u's', u's', u's', u's']

=> (list (take 0 (repeat "s")))
[]

take-nth

Usage: (take-nth n coll)

Returns an iterator containing every n-th member of coll.

=> (list (take-nth 2 [1 2 3 4 5 6 7]))
[1, 3, 5, 7]

=> (list (take-nth 3 [1 2 3 4 5 6 7]))
[1, 4, 7]

=> (list (take-nth 4 [1 2 3 4 5 6 7]))
[1, 5]

=> (list (take-nth 10 [1 2 3 4 5 6 7]))
[1]

take-while

Usage: (take-while pred coll)

Returns an iterator from coll as long as pred returns True.

=> (list (take-while pos? [ 1 2 3 -4 5]))
[1, 2, 3]

=> (list (take-while neg? [ -4 -3 1 2 5]))
[-4, -3]

=> (list (take-while neg? [ 1 2 3 -4 5]))
[]

Included itertools

count cycle repeat accumulate chain compress drop-while remove group-by islice *map take-while tee zip-longest product permutations combinations multicombinations

All of Python's itertools are available. Some of their names have been changed:

  • starmap has been changed to *map
  • combinations_with_replacement has been changed to multicombinations
  • groupby has been changed to group-by
  • takewhile has been changed to take-while
  • dropwhile has been changed to drop-while
  • filterfalse has been changed to remove