Janet 1.39.1-e9c6678 Documentation
(Other Versions: 1.38.0 1.37.1 1.36.0 1.35.0 1.34.0 1.31.0 1.29.1 1.28.0 1.27.0 1.26.0 1.25.1 1.24.0 1.23.0 1.22.0 1.21.0 1.20.0 1.19.0 1.18.1 1.17.1 1.16.1 1.15.0 1.13.1 1.12.2 1.11.1 1.10.1 1.9.1 1.8.1 1.7.0 1.6.0 1.5.1 1.5.0 1.4.0 1.3.1 )

Tuples

Tuples are immutable, sequential types that are similar to arrays. They are represented in source code with either parentheses or brackets surrounding their items. Note that Janet differs from traditional Lisps here, which commonly use the term "lists" to describe forms wrapped in parentheses. Like all data structures, tuple contents can be retrieved with the get function and their length retrieved with the length function.

The two most common ways to create a tuple are using the literal form with bracket characters [] or calling the tuple function directly.

# Four ways to create the same tuple:

(def mytup1 [1 2 3 4])       # using bracket literals
(def mytup2 (tuple 1 2 3 4)) # using the (tuple) function

# the quote prevents form evaluation and returns the tuple directly
(def mytup3 '(1 2 3 4))

# quasiquote works similarly to quote, but allows for some
# forms to be evaluated inside via the , character
(def mytup4 ~(1 2 3 ,(+ 2 2)))

# these all result in the same tuple:
(assert (= mytup1 mytup2 mytup3 mytup4)) # true

As table keys

Tuples can be used as table keys because two tuples with the same contents are considered equal:

(def points @{[0 0] "A"
              [1 3] "B"
              [7 5] "C"})

(get points [0 0])       # "A"
(get points (tuple 0 0)) # "A"
(get points [1 3])       # "B"
(get points [8 5])       # nil (ie: not found)

Sorting tuples

Tuples can also be used to sort items. When sorting tuples via the < or > comparators, the first elements are compared first. If those elements are equal, we move on to the second element, then the third, and so on. We could use this property of tuples to sort all kind of data, or sort one array by the contents of another array.

(def inventory [
 ["ermie" 1]
 ["banana" 18]
 ["cat" 5]
 ["dog" 3]
 ["flamingo" 23]
 ["apple" 2]])

(def sorted-inventory (sorted inventory))

(each [item n] sorted-inventory (print item ": " n))
# apple: 2
# banana: 18
# cat: 5
# dog: 3
# ermie: 1
# flamingo: 23

Bracketed tuples

Under the hood, there are two kinds of tuples: normal (aka paren or non-bracketed), and bracketed ones.

# bracket tuples
(def b-1 (tuple/brackets 1 2 3))
(def b-2 '[1 2 3])

# paren tuples
(def p-1 (tuple 1 2 3))
(def p-2 '(1 2 3))

# tuple/type can distinguish between tuples
(tuple/type b-1) # -> :brackets
(tuple/type b-2) # -> :brackets

(tuple/type p-1) # -> :parens
(tuple/type p-2) # -> :parens

The compiler interprets bracket tuples as a tuple constructor rather than a function call.

# create a function object that returns a tuple
(def c-1 (compile (tuple/brackets 1 2 3)))

# create and return a (paren) tuple with elements 1, 2 and 3
(c-2) # -> (1 2 3)

# create a function object with a call to +
(def c-2 (compile (tuple '+ 1 2 3)))

# call the function named by + with 1, 2 and 3 as arguments
(c-2) # -> 6

Considering that functions evaluate their arguments and the tuple literal ([]) evaluates to a normal (paren) tuple, the behavior of tuple/type can be surprising. It's best to use it with quoted values.

(tuple/type [1 2 3])  # -> :parens

(tuple/type '(1 2 3)) # -> :parens
(tuple/type '[1 2 3]) # -> :brackets

(eval-string "[1 2 3]")  # -> (1 2 3)
(eval-string "'[1 2 3]") # -> [1 2 3]

When printed via pp, bracket tuples are printed with square brackets instead of parentheses.

(pp (tuple/brackets 1 2 3))
# [1 2 3]

(pp (tuple 1 2 3))
# (1 2 3)

# this can be surprising
(pp [1 2 3])
# (1 2 3)

Bracket and paren tuples with the same contents are not =, but are deep=.

(=     '() '[]) # -> false
(deep= '() '[]) # -> true

(=     '(1 2 3) '[1 2 3]) # -> false
(deep= '(1 2 3) '[1 2 3]) # -> true

In all other ways, bracketed tuples behave identically to normal tuples.

You should use bracketed tuples only in code that will be evaluated later (for example in macros).

More functions

Most functions in the core library that work on arrays also work on tuples, or have an analogous function for tuples. See the Tuple API for a list of functions that operate on tuples.