Lists
As it mentioned above lists are dynamically allocated arrays of items with the same type. List variable is initialized by it’s initial value or empty list if initial value is not specified. List elements are indexed, starting from 1. List items can be accessed directly after their definition. [1, 2, 3][1]
will give 1
, of course this thing just has no sense.
List constant
Constant lists can be defined as well as atomic values. Examples:
const l1 := [1, 2, 3, 4]; # list of ints
const l2 := ["one", "two"]; # list of strings
Also empty list constant can be defined using next construction.
const l3 := []; # empty list
Empty list doesn’t has item type and can be assigned to or compared with any other list.
const l4 := [1, "hello"]; # list(any)
If types of elements are different list is recognized as list(any)
. These constants can’t be used without proper type casting.
List length
To determine a list length Jarog has a special unary operator @
. It’s result is integer and is equal to a list size.
const l := [1, 2, 3];
const list_len := @len; # will give 3
All lists in Jarog are immutable and their size cannot be changed. But list variables can be reassigned with a new values.
Concatenating lists
Two lists can be concatenated into one if their types are compatible.
const l := [1, 2, 3] + [3, 4]; # will give [1, 2, 3, 3, 4]
In this way new items can be added to existing list.
var a: list(int) := [1, 2, 3];
a := a + [4]; # a is [1, 2, 3, 4] now
In case of extending list type the result type will be widened.
const l := [1, 2, 3] + [1.1, 1.2]; # first list contains integers only
# but result type will be list(float)
Remember you can not get list(any)
by concatenating two list with different types but it still can be done by casting them to list(any)
.
const l1 := [1, 2, 3] + ["foo", "bar"]; # will throw an exception
const l2 := [1, 2, 3]'list(any) + ["foo", "bar"]'list(any); # ok
List indexing
As it was told above list elements are indexed starting from 1. The first element has index 1 and the last element’s index is equal the list length. Index is solid and can’t have any windows.
const a = [2, 4, 8, 16, 32, 64];
const b = a[1]; # b is 2
const c = a[@a]; # c is 64
Index can be negative, negative index is counted from the end of the list. -1 is the last element of the list.
const a = [2, 4, 8, 16, 32, 64];
const b = a[-1]; # b is 64 now
const c = a[-@a]; # c is 2
Sublists
List elements can be accessed one by one as well as by list of integers. Elements are taken one by one starting from the first index to the last index. If index list contains duplicates, fetched values will be also duplicated. Trick with negative index also works here.
const a = [2, 4, 8, 16, 32, 64];
const b = a[[2, 3, 4]]; # [4, 8, 16]
const b = a[2:4]; # [4, 8, 16], range is used
const c = a[4:2]; # [16, 8, 4]
const d = a[1:-1]; # will throw an error as 1:-1 gives
# [1, 0, -1], zero element never exists
List decomposition
List can be decomposed and assigned to one or multiple values at once:
var a, b: int;
[a, b] := [1, 2];
Number of elements on both sides can be different. If left list is shorter then some values from the end of the right list will be lost. If left list is longer only first elements will be reassigned with new values.
var a, b, c: int;
[a, b] := [1, 2, 3]; # 3 is lost
[a, b, c] := [1, 2]; # c is still the same as before assigning
This allows to do things like next:
const f := $(): list(int) do
return [1, 2, 3];
end;
var a, b: int;
[a, b] := f(); # only first two elements are assigned, if function
# returns empty list no values are assigned at all