6.27. kink/VEC

6.27.1. type vec

`vec` is a mutable and variable-length sequence of values.

Elements of a `vec` are indexed using consequent integers starting from 0.

A `vec` is a subtype of `plain_param`. See kink/param/PLAIN_PARAM.

6.27.1.1. Vec.get(Ind)

`get` returns the element at the index `Ind`.

Precondition

`Ind` must be an integer `num` in the range [0, Vec.size).

Example

6.27.1.2. Vec.size

`size` returns the number of elements of `Vec` as an integer `num` value.

Example

6.27.1.3. Vec.front

`front` returns the first element of `Vec`.

Precondition

`Vec` must not be empty.

Example

6.27.1.4. Vec.back

`back` returns the last element of `Vec`.

Precondition

`Vec` must not be empty.

Example

6.27.1.5. Vec.take_front(N)

`take_front` returns a new `vec` containing the first `N` elements of `Vec`.

Precondition

`N` must be an integer `num` in the range [0, Vec.size].

Example

6.27.1.6. Vec.take_back(N)

`take_back` returns a new `vec` containing the last `N` elements of `Vec`.

Precondition

`N` must be an integer `num` in the range [0, Vec.size].

Example

6.27.1.7. Vec.drop_front(N)

`drop_front` returns a new `vec` which contains the elements of the slice of `Vec` in the range [N, Vec.size).

Precondition

`N` must be an integer `num` in the range [0, Vec.size].

Example

6.27.1.8. Vec.drop_back(N)

`drop_back` returns a new `vec` which contains the elements of the slice of `Vec` in the range [0, Vec.size - N).

Precondition

`N` must be an integer `num` in the range [0, Vec.size].

Example

6.27.1.9. Vec.slice(From To)

`slice` returns a new `vec` which contains the elements of the slice of `Vec` in the range [From, To).

Preconditions

`From` and `To` must be integer `num` values.

0 <= From <= To <= Vec.size

Example

6.27.1.10. Vec.set(Ind Val)

`set` stores `Val` at the index `Ind`.

The size of `Vec` does not change.

Precondition

`Ind` must be an integer `num` in the range [0, Vec.size).

Example

6.27.1.11. Vec.push_front(Val)

`push_front` inserts `Val` as the first element of `Vec`.

The size of `Vec` is extended by one. The existing elements are copied to the back by one.

Example

6.27.1.12. Vec.push_back(Val)

`push_back` inserts `Val` as the last element of `Vec`.

The size of `Vec` is extended by one.

Example

6.27.1.13. Vec.push_at(Pos Val)

`push_at` inserts `Val` at the index `Pos`.

The size of `Vec` is extended by one. The existing elements at and after `Pos` are copied to the back by one.

Preconditions

`Pos` must be an integer `num`.

0 <= Pos <= Vec.size

Example

6.27.1.14. Vec.append_front(Eacher)

`append_front` inserts all the elements of `Eacher` to the front of `Vec`.

If Eacher.each passes E(0), E(1), ,,, E(n-1) to $consume for each invocation, and `Vec` currently contains V(0), V(1), ,,, V(m-1), the elements of Vec will be E(0) E(1) ,,, E(n-1) V(0) V(1) ,,, V(m-1) after the invocation of `append_front`.

Precondition

`Eacher` must support each($consume) method, which calls $consume with each element of `Eacher`.

Example

6.27.1.15. Vec.append_back(Eacher)

`append_back` inserts all the elements of `Eacher` to the back of `Vec`.

If Eacher.each passes E(0), E(1), ,,, E(n-1) to $consume for each invocation, and `Vec` currently contains V(0), V(1), ,,, V(m-1), the elements of Vec will be V(0) V(1) ,,, V(m-1) E(0) E(1) ,,, E(n-1) after the invocation of `append_back`.

Precondition

`Eacher` must support each($consume) method, which calls $consume with each element of `Eacher`.

Example

6.27.1.16. Vec.append_at(Pos Eacher)

`append_at` inserts all the elements of `Eacher` to `Vec` at the index `Pos`.

If Eacher.each passes E(0), E(1), ,,, E(n-1) to $consume for each invocation, and `Vec` currently contains V(0), V(1), ,,, V(m-1), the elements of `Vec` will be V(0), V(1) ,,, V(Pos-1), E(0), E(1) ,,, E(n-1), V(Pos) ,,, V(m-1) after the invocation of `append_at`.

Preconditions

`Pos` must be an integer `num`.

0 <= Pos <= Vec.size

`Eacher` must support each($consume) method, which calls $consume with each element of `Eacher`.

Example

6.27.1.17. Vec.pop_front

`pop_front` removes the first element of `Vec` and returns the removed element.

The elements after the removed element are copied to the front by one. The size of `Vec` is curtailed by one.

Precondition

`Vec` must not be empty.

Example

6.27.1.18. Vec.pop_back

`pop_back` removes the last element of `Vec` and returns the removed element.

The size of `Vec` is curtailed by one.

Precondition

`Vec` must not be empty.

Example

6.27.1.19. Vec.pop_at(Ind)

`pop_at` removes the element at the index `Ind` and returns the removed element.

The elements after the removed element are copied to the front by one. The size of `Vec` is curtailed by one.

Preconditions

`Ind` must be an integer `num`.

0 <= Ind < Vec.size

Example

6.27.1.20. Vec.clear(...[From=0 To=Vec.size])

`clear` removes the elements from `Vec` in the slice of the range [From, To).

The elements after the removed slice are copied to the front by (To - From). The size of `Vec` is curtailed to Vec.size - (To - From).

Preconditions

`From` and `To` must be integer `num` values.

0 <= From <= To <= Vec.size

Example: with no arg

Example: with From

Example: with From and To

6.27.1.21. Dest_vec.move(D_from Src ...[S_from=0 S_to=Src.size])

`move` copies the elements of the slice [S_from, S_to) of `Src` vector, and pastes them to the slice [D_from, D_from + (S_to - S_from)) of `Dest_vec` vector.

The name `move` comes from `memmove` function, as `Dest_vec` and `Src` can be the same vector, and slices can overlap.

Preconditions

`D_from` must be an integer `num` in the range [0, Dest_vec.size].

`Src` must be a `vec`.

`S_from` and `S_to` must be integer `num` values.

0 <= S_from <= S_to <= Src.size

D_from + (S_to - S_from) <= Dest_vec.size

Example

6.27.1.22. Vec.dup

`dup` makes a new `vec` containing the same sequence of elements as `Vec` has.

Example

6.27.1.23. Vec.reverse

`reverse` makes a new `vec` containing the same elements as `Vec` has, in the reversed order.

Example

6.27.1.24. Vec.concat

`concat` concatenates `vec`s in `Vec`.

`concat` assumes all the elements of `Vec` are `vec`s. `concat` returns a new `vec` which has all the elements of those `vec`s in the order of those `vec`s, and in the order of the elements of thsoe `vec`s.

Precondition

All the elements of `Vec` must be `vec`s.

Example

6.27.1.25. Vec.unconcat(N)

`unconcat` splits `Vec` into groups of `N` elements, and returns a new `vec` of `vec`s which have those `N` elements.

If `Vec` contains E(0), E(1) ,,, E(N-1), E(N), E(N+1) ,,, E(N+(N-1)) ,,, E(m*N), E(m*N+1) ,,, E(m*N+(N-1)), the result `vec` will contain `vec`s [E(0) E(1) ,,, E(N-1)], [E(N) E(N+1) ,,, E(N+(N-1))] ,,, [E(m*N) E(m*N+1) ,,, E(m*N+(N-1))].

Preconditions

`N` must be a positive integer `num`.

Vec.size % N == 0

Example

6.27.1.26. Vec.just(...[$if_empty])

`just` assumes `Vec` has only one element, and returns the element.

If `Vec` is empty, and $if_empty is passed, `just` tail-calls $if_empty.

Otherwise, `just` raises an exception.

Precondition

$if_empty must be a thunk.

Example

6.27.1.27. Vec.with_elems(...[$with0 $with1 $with2 ,,,])

`with_elems` tail-calls a fun with the elements of `Vec` as args.

`with_elems` takes an arbitrary number of funs. Let these be $with0, $with1, $with2, ,,, in that order. If the size of `Vec` is `N`, `with_elems` tail-calls $withN with the elements of `Vec` as args.

Preconditions

The size of `Vec` must be less than the number of args.

$withK (K = 0, 1, 2 ,,,) must take K args.

Example

6.27.1.28. Vec.each($consume)

`each` calls $consume with each element from the front to the back.

If `Vec` is not empty, `each` tail-calls $consume for the last element.

Precondition

$consume must be a fun which takes a value.

Example

6.27.1.29. Vec.map($transform)

`map` makes a `vec` whose elements are transformed from the elements of `Vec` by $transform.

If `Vec` contains E(0), E(1) ,,, E(n-1), the result `vec` will contain transform(E(0)) transform(E(1)) ,,, transform(E(n-1)).

Precondition

$transform must be a fun which takes a value.

Example

6.27.1.30. Vec.concat_map($to_vec)

`concat_map` returns a `vec` which concatenates `vec`s which are results of to_vec(element-of-Vec)

Precondition

$to_vec must be a fun which takes a value and returns a `vec`.

Example

6.27.1.31. Vec.filter($include?)

`filter` returns a `vec` containing all the elements that satisfy the predicate $include?.

Precondition

$include? must be a predicate.

Example

6.27.1.32. Vec.count($counted?)

`count` returns the number of elements which satisfy the predicate $counted?, as an integer `num`.

Precondition

$counted? must be a predicate.

Example

6.27.1.33. Vec.fold(Init $combine)

`fold` folds elements seeded by `Init`.

If `Vec` contains elements E(0) E(1) ,,, E(n-1), the result will be combine(combine(,,, combine(combine(Init E(0)) E(1)) ,,,) E(n-1)).

Precondition

$combine must take two values.

Example

6.27.1.34. Vec.reduce($combine ...[$empty_fallback])

`reduce` accumulates elements of `Vec` mutually.

If `Vec` has one or more elements, `reduce` tail-calls `Vec.drop_front(1).fold(Vec.front $combine)`.

If `Vec` is empty, and $empty_fallback is given, `reduce` tail-calls $empty_fallback with no arg.

If `Vec` is empty, and $empty_fallback is not given, `reduce` raises an exception.

Preconditions

$combine must be a fun which takes two values.

$empty_fallback must be a thunk.

Example: without fallback

Example: with fallback

6.27.1.35. Vec.take_while($include?)

`take_while` returns a `vec` of the longest initial prefix whose elements satisfy the predicate $include?.

Precondition

$include? must be a predicate.

Example

6.27.1.36. Vec.drop_while($exclude?)

`drop_while` returns a `vec` of the elements after the longest initial prefix whose elements satisfy the predicate $exclude?.

Precondition

$exclude? must be a predicate.

Example

6.27.1.37. Vec.all?($match?)

`all?` returns whether all the elements of `Vec` satisfy the predicate $match?.

Precondition

$match? must be a predicate.

Example

6.27.1.38. Vec.any?(...[$match?={ true }])

`any?` returns whether at least one of the elements of `Vec` satisfies the predicate $match?.

$match? is an optional arg with a default value { true }, So, if $match? is not passed, `any?` returns whether `Vec` is nonempty.

Precondition

$match? must be a predicate.

Example

Example

6.27.1.39. Vec.have?(Target)

`have?` returns whether `Vec` has an element which is equal to `Target` by `==` operator, or `op_eq` method.

Calling Vec.have?(Target) is equivalent to calling Vec.any?{(:E) Target == E }.

Example

6.27.1.40. Vec.have_all?(Vals)

`have_all?` returns whether `Vec` has all the elements of `Vals`.

Calling Vec.have_all?(Vals) is equivalent to calling Vals.all?{(:T) Vec.have?(T) }.

Preconditions

`Vals` must have all?($match?) method.

`==` operator, or `op_eq` method, must be able to compare elements of `Vec` and `Vals`.

Example

6.27.1.41. Vec.have_any?(Vals)

`have_any?` returns whether `Vec` has any element of `Vals`.

Calling Vec.have_any?(Vals) is equivalent to calling Vals.any?{(:T) Vec.have?(T) }.

Preconditions

`Vals` must have any?($match?) method.

`==` operator, or `op_eq` method, must be able to compare elements of `Vec` and `Vals`.

Example

6.27.1.42. Vec.sort(...[$up_to?={(:X :Y) X <= Y }])

`sort` returns a `vec` whose elements are copied from `Vec` and sorted in the ascending order specified by $up_to?.

Comparison

Comparison of elements are done by $up_to?.

$up_to? must be a total order relation of the elements of `Vec`. For all `X`, `Y`, and `Z` in the elements of `Vec`, $up_to? must satisfy the following.

• reflexive: up_to?(X X)

• transitive: if up_to?(X Y) && up_to?(Y Z) then up_to?(X Z)

• antisymmetric: if up_to?(X Y) && up_to?(Y X) then X is equivalent to Y

• strongly connected: up_to?(X Y) || up_to?(Y X)

Stable sort

`sort` performs a stable sort. If up_to?(E1 E2) && up_to?(E2 E1), for `E1` and `E2` in `Vec`, `E1` and `E2` appear in the result `vec` in the same order as in `Vec`.

Precondition

$up_to? must be a function which takes two values and returns a `bool`.

Example

6.27.1.43. Vec.iter(...[From=0 To=Vec.size])

`iter` method returns an `iter` containing the elements of the slice in the range [From, To).

Preconditions

`From` and `To` must be integer `num` values.

0 <= From <= To <= Vec.size

Example

6.27.1.44. Vec1 + Vec2

`+` operator, or `op_add` method, returns a `vec` containing all the elements of `Vec1` in the front, and all the elements of `Vec2` in the back.

Precondition

`Vec2` must be a `vec`.

Example

6.27.1.45. Vec * N

`*` operator, or `op_mul` method, returns a `vec` containing the elements of `Vec` repeated `N` times.

Preconditions

`N` must be a nonnegative integer `num`.

Example

6.27.1.46. Vec1 == Vec2

`==` operator, or `op_eq` method, returns whether `Vec1` and `Vec2` are equal, or they contain equal elements in the same order.

The two vecs are equal if:

1) Vec1.size == Vec2.size

2) For all i in [0, Vec1.size), Vec1.get(i) == Vec2.get(i)

The conditions are tested in the numbered order, and from the smallest `i` to the biggest `i`. If a test returns false, subsequent tests are not evaluated and two vecs are decided not equal.

Precondition

`Vec1` and `Vec2` must be `vec` values.

Example

6.27.1.47. Vec1 <= Vec2

`<=` operator, or `op_le` method, returns whether `Vec1` is less than or equal to `Vec2` by the order defined by `<=` operator of the elements.

`Vec1` is less than or equal to `Vec2` when:

1) There is a nonnegative integer k (k < min(Vec1.size Vec2.size)), such that for all i in [0, k) Vec1.get(i) <= Vec2.get(i) && Vec2.get(i) <= Vec1.get(i), and ! (Vec2.get(k) <= Vec1.get(k)); or

2) Vec1.size <= Vec2.size and for all i in [0, Vec1.size), Vec1.get(i) <= Vec2.get(i) && Vec2.get(i) <= Vec1.get(i).

Comparisons are done from the smallest index to the biggest index. When the result is determined, the subsequent comparisons are not performed.

Precondition

`Vec2` must be a `vec`.

Example

6.27.1.48. Lhs <- Rhs

`<-` operator, or `op_store` method, performs multiple assignment between a `vec` on the left hand side, `Lhs`, and the `vec` on the right hand side, `Rhs.

Here, elements of `Lhs` are called params, and elements of `Rhs` are called args.

Params and args

There are three types of params:

• plain_param: ex. varref, vec. Can receive 1 arg.

• opt_param: ex. Varref.opt. Can receive 0 or 1 arg.

• rest_param: ex. Varref.rest. Can receive an arbitrary number of args.

`plain_param` and `opt_param` can appear any number of times in `Lhs`. An `opt_param` cannot precede a `plain_param`.

`Lhs` can have zero or one `rest_param` at the back.

Let `NP` be the number of `plain_param`, and `NO` be the number of `opt_param`. Here, P(0), P(1) ,,, P(NP-1), O(0), O(1) ,,, O(NO-1) are params, where P(i) for each i (0 <= i < NP) is a `plain_param`, and O(j) for each j (0 <= j < NO) is an `opt_param`.

In addition, let `NA` be the number of args, and A(k) for each k (0 <= k < NA) be an arg.

`op_store` behaves differently depending on whether `Lhs` has a `rest_param` or not.

When `Lhs` has no `rest_param`

In this case, the number of args `NA` is valid when NP <= NA <= NP+NO.

When the number of args is not valid, `op_store` raises an exception.

When the number of args is valid, `op_store` calls a method of each param as follows:

• P(k).op_store(A(k)) for each k (0 <= k < NP)

• O(k - NP).pass_arg(A(k)) for each k (NP <= k < NA)

• O(k - NP).pass_nothing for each k (NA <= k < NP+NO)

When `Lhs` has a `rest_param`, `R`

In this case, the number of args `NA` is valid when NP <= NA.

When the number of args is not valid, `op_store` raises an exception.

When the number of args is valid, `op_store` calls a method of each param as follows:

• P(k).op_store(A(k)) for each k (0 <= k < NP)

• O(k - NP).pass_arg(A(k)) for each k (NP <= k < NA)

• O(k - NP).pass_nothing for each k (NA <= k < NP+NO)

• R.pass_rest(vec of A(k) for each k (NP+NO <= k < NA))

Precondition

`Rhs` must be a `vec`.

Example

6.27.1.49. Vec.repr

`repr` returns a `str` representation of `Vec`.

Example

6.27.2. VEC.is?(Val)

`is?` returns whether `Val` is a `vec`.

6.27.3. VEC.from_each(Eacher)

`from_each` returns a new `vec` including all the elements of `Eacher`.

`Eacher` must have .each($consume) method which calls $consume for each element.

Example