Skip to content
Xen / docs

Search documentation

English · v0.1.0-demo.2

Type to search the documentation.

    한국어
    Xen / learn v0.1.0-demo.2

    Slices and iterators

    Before passing a collection, decide whether you need independent items, a temporary view of the original, or ownership of its contents. This chapter connects collections with ownership.

    MethodRelationship to the originalItem constraints
    Pass Vec<T> by valueIndependent copy for cloneable items; whole-vector move for move-only itemsDepends on the item type.
    as_slice(), slice(start, end)Read-only view without copying itemsOriginal cannot change or move until the view’s last use.
    .iter()Borrows the source and provides copied or cloned itemsItems must be copyable or cloneable.
    .into_iter()Takes the vector and yields owned items in orderSupports move-only items such as Box and File.

    for value in values does not automatically create a vector iterator. Iterator methods require use std.iter;.

    Last use of a view and a transformation pipeline

    Section titled “Last use of a view and a transformation pipeline”

    Save this as views_and_iterators.xen:

    views_and_iterators.xen
    use std.iter;
    fn doubled(value: Int) -> Int {
    return value * 2;
    }
    #![explc]
    fn over_two(value: &Int) -> Bool {
    return *value > 2;
    }
    fn main() {
    let mut values = [1, 2, 3];
    let view = values.slice(0, 2);
    println(view.get(1));
    values.push(4);
    for value in values.iter().map(doubled).filter(over_two) {
    println(value);
    }
    let owned = [box(10), box(20)];
    for item in owned.into_iter() {
    println(item.into_inner());
    }
    }
    Terminal window
    xen check views_and_iterators.xen
    xen run views_and_iterators.xen
    views_and_iterators.stdout
    2
    4
    6
    8
    10
    20

    slice(0, 2) views items 0 and 1; the end index 2 is excluded. println(view.get(1)) is the last use of the view, so values.push(4) is allowed on the next line.

    map(doubled) doubles each value, then filter(over_two) keeps transformed values greater than 2. Callbacks execute during iteration, rather than when the chain is created. A filter callback receives a shared reference to an item, which is why over_two has #![explc]. main creates no explicit references such as &value.

    The final vector contains Box<Int> values. .into_iter() yields ownership of each box, and into_inner() takes out its integer. owned cannot be used after this iteration.

    Diagnose mutation while a view is still in use

    Section titled “Diagnose mutation while a view is still in use”

    This program deliberately fails. Run xen check borrow_error.xen:

    borrow_error.xen
    fn main() {
    let mut values = [1, 2];
    let view = values.as_slice();
    values.push(3);
    println(view.get(0));
    }
    borrow_error.stderr
    cannot mutate 'values' while it is borrowed

    The view is used after push, so mutation is rejected. Move println(view.get(0)); before push to finish using the view before changing the original. Copying items into a new vector is another choice, but creating a Slice itself does not copy them.

    You cannot copy a Box or File out with values[0] or get(0). Remove an owned item with pop(), replace(), or .into_iter(). To read an item without taking it, create &values[index] inside an explc scope. Mutable element references are unavailable.

    pop() on an empty vector and get() with an invalid index cause runtime errors. Check the length first; get() does not return an Option on failure.

    Keep views within their supported lifetime

    Section titled “Keep views within their supported lifetime”

    Read-only views cannot be returned from functions or stored as vector items; mutable views are unavailable. String.as_bytes() produces a Slice<U8>. Byte views do not provide character indexing either.

    Look up methods in the collection chapter and iterator reference.

    Add println(view.get(0)); after values.push(4) in the working program and inspect the error. Explain why replacing owned.into_iter() with owned.iter() cannot consume the boxes in the same way.