# 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]` 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 + ;                  # 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;                     # 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``````