7 Predefined Types and Functions
7.1 Numbers
type | |
expression | |
| |
expression | |
| |
expression | |
| |
expression | |
| |
expression | |
| |
expression | |
The usual precedence and associativity rules apply, except that / or mod cannot appear to the right of *.
- Int
11
> 3 mod 2
- Int
1
- Int
-12
These operators have lower precedence than arithmetic operators.
- Boolean
#true
> min(1, 2)
- Int
1
> max(1, 2)
- Int
2
> add1(0)
- Int
1
> sub1(0)
- Int
-1
> is_even(2)
- Boolean
#true
> is_odd(2)
- Boolean
#false
7.2 Booleans and Equality
type | |
These operators have lower precedence than arithmetic operators.
- Boolean
#true
For mutable values, == checks whether the values are equal “now,” even though they may be changed to be different in the future (and != checks that values are not equal now).
These operators have lower precedence than all other operators, and || has lower precedence than &&.
- Boolean
#true
- Boolean
#false
7.3 Void
type | |
7.4 Strings
type | |
function | |
|
> string_append("apple", "banana")
- String
"applebanana"
function | |
|
> to_string(1)
- String
"1"
> to_string("apple")
- String
"apple"
> to_string([1, 2, 3])
- String
"[1, 2, 3]"
- String
"#<function:fun>"
- String
"fun (x):« x »"
> "a" +& "b"
- String
"ab"
> "a" +& 1
- String
"a1"
> 1 +& "a"
- String
"1a"
> "choices are " +& [1, 2, 3]
- String
"choices are [1, 2, 3]"
3
> block:
print("a")
print("b")
println("")
ab
type | |
function | |
|
> string_get("apple", 0)
- Char
#{#\a}
> substring("apple", 1, 4)
- String
"ppl"
7.5 Symbols
A symbol is similar to a string in that it simply comprises a sequence of characters, but a symbol expression is written with a #' prefix, instead of in double quotes. Also, the character sequence of a symbol must be valid for an identifier.
Symbols are used primarily as the representation of an identifier within quoted code as a syntax object. For example, the syntax object 'f(apple)' wraps the symbols #'f and #'apple, while 'f("apple")' wraps a symbol #'f and a string "apple". The difference in those examples is between representing a function call whose argument is the variable apple versus a function call whose argument is the string "apple".
type | |
> #'apple
- Symbol
#'apple
> "apple"
- String
"apple"
function | |
|
> string_to_symbol("apple")
- Symbol
#'apple
7.6 Lists
A list has a sequence of elements of a uniform type. That is, the elements of a list can have any type, but they must all have the same type for a given list. See also tuples.
A list is written with square brackets, such as [1, 2, 3]. Using square brackets implicitly uses the #%brackets form, but #%brackets is normally not written.
[]
cons(first_elem, rest_list)
expression | |
|
> [1, 2, 3 + 4]
- Listof(Int)
[1, 2, 7]
> ["apple", "banana"]
- Listof(String)
["apple", "banana"]
> []
- Listof(?_a)
[]
function | |
| |
function | |
| |
function | |
| |
function | |
| |
function | |
The first and rest functions raise an exception when given an empty list. The cons, first, and rest functions take O(log n) time for a list of length n, and is_cons and is_empty take constant time.
> cons(1, [2, 3])
- Listof(Int)
[1, 2, 3]
> first(["apple", "banana", "coconut"])
- String
"apple"
> rest(["apple", "banana", "coconut"])
- Listof(String)
["banana", "coconut"]
> first([])
- ?_a
first: failed on empty list
> length(["apple", "banana"])
- Int
2
> list_get(["apple", "banana"], 1)
- String
"banana"
> def my_list = [1, 2, 3]
> def my_other_list = [3, 4]
> append(my_list, my_other_list)
- Listof(Int)
[1, 2, 3, 3, 4]
> my_list
- Listof(Int)
[1, 2, 3]
> reverse([1, 2, 3])
- Listof(Int)
[3, 2, 1]
> member(2, [1, 2, 3])
- Boolean
#true
> member(4, [1, 2, 3])
- Boolean
#false
- Listof(Int)
[2, 3, 4]
- Listof(String)
["1", "2", "3"]
- Listof(Int)
[5, 7, 9]
- Listof(Int)
[2, 4]
- Listof(Int)
[1, 3]
function | ||
| ||
| ||
function | ||
|
- Int
16
- Listof(String)
["3", "2", "1"]
- Listof(String)
["1", "2", "3"]
7.7 Arrays
Like a list, an array has a sequence of elements of a uniform type. Unlike a list, any element of the array can be accessed in constant time using square-bracket indexing, as in a[0]. Further unlike a list, an array is mutable, and an array element can be changed by commbining square brackets with := for assignment, as in a[0] = 1.
An array is created with Array, such as Array(1, 2, 3), or with make_array. Using square brackets implicitly uses the #%index form, but #%index is normally not written.
- Arrayof(Int)
Array(1, 2, 7)
expression | |
| |
expression | |
> a[0]
- String
"a"
> a[0] := "z"
- Void
> a[0]
- String
"z"
> a
- Arrayof(String)
Array("z", "b", "c")
> a[0, 0]
#%index: unexpected term
> make_array(3, "a")
- Arrayof(String)
Array("a", "a", "a")
function | |
|
> array_length(Array("a", "b", "c"))
- Int
3
7.8 Boxes
A box is a mutable object that holds a single value.
function | |
| |
function | |
| |
function | |
> b
- Boxof(Int)
box(1)
> unbox(b)
- Int
1
> set_box(b, 2)
- Void
> unbox(b)
- Int
2
> set_box(b, "apple")
typecheck failed: Int vs. String
7.9 Options
An option encapsulates the idea of a computation that may fail.
An option is either a “failure” without a value or “success” with a value:
7.10 Tuples
A tuple is similar to a list, but its type reflects a fixed number of elements in the tuple, and the elements can have different types. A tuple of one element is equivalent to just the element.
The * type operator for tuples has higher precedence (i.e., joins more tightly) than the -> type operator for functions.
> values(1, "apple")
- Int * String
values(1, "apple")
> values()
- ()
values()
- Int * (Int -> Int)
values(1, #<function:fun>)
In general extract components of a tuple by using def values.
> tup
- Int * String * (?a -> ?a)
values(1, "apple", #<function:fun>)
> str
- String
"apple"
Parentheses are normally used for mere grouping, but emprt parentheses form the type of an empty tuple.
7.11 Maps
A map (not to be confused with the map function on lists), also known as a dictionary, is a mapping from keys to values. All keys must have the same type, and all values must have the same type.
A map is written with curly braces {} around comma-separated key–value pairs, where the key and value are separated by a colon :, as in {"a": 1, "b": 2}. Using curly braces implicitly uses the #%braces form, but #%braces is normally not written.
Since the result map is immutable, it works with map_update, but not map_set.
> { "a": 1, "b": 2 }
- Mapof(String, Int)
{"a": 1, "b": 2}
expression | |
|
Since the result map is mutable, it works with map_set, but not map_update.
> MutableMap{ "a": 1, "b": 2 }
- Mapof(String, Int)
MutableMap{"a": 1, "b": 2}
The map_get_k function calls either success_k or fail_k and returns the result, depending on whether key is mapped. The call map_get(map, key) is equivalent to map_get_k(map, key, some, none).
> def m = { "a": 1, "b": 2 }
> map_get(m, "a")
- Optionof(Int)
some(1)
> map_get(m, "c")
- Optionof(Int)
none()
- Int
1
- Int
0
> def m = { "a": 1, "b": 2 }
> map_update(m, "a", 100)
- Mapof(String, Int)
{"a": 100, "b": 2}
> map_update(m, "c", 3)
- Mapof(String, Int)
{"a": 1, "b": 2, "c": 3}
> m
- Mapof(String, Int)
{"a": 1, "b": 2}
> def m = MutableMap{ "a": 1, "b": 2 }
> map_set(m, "a", 100)
- Void
> map_set(m, "c", 3)
- Void
> m
- Mapof(String, Int)
MutableMap{"a": 100, "b": 2, "c": 3}
> map_remove({ "a": 1, "b": 2}, "a")
- Mapof(String, Int)
{"b": 2}
> def m = MutableMap{ "a": 1, "b": 2 }
> map_delete(m, "a")
- Void
> m
- Mapof(String, Int)
MutableMap{"b": 2}
> map_keys({ "a": 1, "b": 2 })
- Listof(String)
["b", "a"]