Janet 1.38.0-73334f3 Documentation
(Other Versions:
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
)
Data Structures
Once you have a handle on functions and the primitive value types, you may be wondering how to work with collections of things. Janet has a small number of core data structure types that are very versatile. Tables, structs, arrays, tuples, strings, and buffers, are the 6 main built-in data structure types. These data structures can be arranged in a useful table describing their relationship to each other.
Interface | Mutable | Immutable |
---|---|---|
Indexed | Array | Tuple |
Dictionary | Table | Struct |
Bytes | Buffer | String (Symbol, Keyword) |
Indexed types are linear lists of elements than can be accessed in constant time with an integer index. Indexed types are backed by a single chunk of memory for fast access, and are indexed from 0 as in C. Dictionary types associate keys with values. The difference between dictionaries and indexed types is that dictionaries are not limited to integer keys. They are backed by a hash table and also offer constant time lookup (and insertion for the mutable case). Finally, the 'bytes' abstraction is any type that contains a sequence of bytes. A 'bytes' value or byteseq associates integer keys (the indices) with integer values between 0 and 255 (the byte values). In this way, they behave much like arrays and tuples. However, one cannot put non-integer values into a byteseq.
The table below summarizes the big-O complexity of various operations and other information on the built-in data structures. All primitive operations on data structures will run in constant time regardless of the number of items in the data structure.
Data Structure | Access | Insert/Append | Delete | Space Complexity | Mutable |
---|---|---|---|---|---|
Array * | O(1) | O(1) | O(1) | O(n) | Yes |
Tuple | O(1) | - | - | O(n) | No |
Table | O(1) | O(1) | O(1) | O(n) | Yes |
Struct | O(1) | - | - | O(n) | No |
Buffer | O(1) | O(1) | O(1) | O(n) | Yes |
String/Keyword/Symbol | - | - | - | O(n) | No |
*: Append and delete for an array correspond to array/push
and
array/pop
. Removing or inserting elements at random indices will run in
O(n)
time where n
is the number of elements in the array.
(def my-tuple (tuple 1 2 3))
(def my-array @(1 2 3))
(def my-array (array 1 2 3))
(def my-struct {
:key "value"
:key2 "another"
1 2
4 3})
(def another-struct
(struct :a 1 :b 2))
(def my-table @{
:a :b
:c :d
:A :qwerty})
(def another-table
(table 1 2 3 4))
(def my-buffer @"thisismutable")
(def my-buffer2 @``This is also mutable``)
To read the values in a data structure, use the get
or in
functions.
The first
parameter is the data structure itself, and the second parameter is the key. An
optional third parameter can be used to specify a default if the value is not
found.
(get @{:a 1} :a) # -> 1
(get {:a 1} :a) # -> 1
(in {:a 1} :a) # -> 1
(get @[:a :b :c] 2) # -> :c
(in @[:a :b :c] 2) # -> :c
(get (tuple "a" "b" "c") 1) # -> "b"
(get @"hello, world" 1) # -> 101
(get "hello, world" 1) # -> 101
(in "hello, world" 1) # -> 101
(get {:a :b} :a) # -> :b
(get {:a :b} :c :d) # -> :d
(in {:a :b} :c :d) # -> :d
The in
function (added in v1.5.0) for tables and structs behaves
identically to get
. However, the in
function for arrays, tuples,
and string-likes will throw errors on bad keys --- so to better detect errors,
prefer in
for these.
(get @[:a :b :c] 3) # -> nil
(in @[:a :b :c] 3) # -> raises error
To update a mutable data structure, use the put
function. It
takes 3 arguments, the data structure, the key, and the value, and
returns the data structure. The allowed types of keys and values
depend on the data structure passed in.
(put @[] 100 :a)
(put @{} :key "value")
(put @"" 100 92)
Note that for arrays and buffers, putting an index that is outside the length of
the data structure will extend the data structure and fill it with nil
s
in the case of the array, or 0
s in the case of the buffer.
The last generic function for all data structures is the length
function.
This returns the number of values in a data structure (the number of keys in a
dictionary type).