Slices and iterators
This topic is not available in the selected language or version. Showing the start of this section.
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.
Choose copying, viewing, or consuming
Section titled “Choose copying, viewing, or consuming”| Method | Relationship to the original | Item constraints |
|---|---|---|
Pass Vec<T> by value | Independent copy for cloneable items; whole-vector move for move-only items | Depends on the item type. |
as_slice(), slice(start, end) | Read-only view without copying items | Original cannot change or move until the view’s last use. |
.iter() | Borrows the source and provides copied or cloned items | Items must be copyable or cloneable. |
.into_iter() | Takes the vector and yields owned items in order | Supports 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:
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()); }}xen check views_and_iterators.xenxen run views_and_iterators.xen24681020slice(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:
fn main() { let mut values = [1, 2]; let view = values.as_slice(); values.push(3); println(view.get(0));}cannot mutate 'values' while it is borrowedThe 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.
Take move-only items
Section titled “Take move-only items”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.
Try it
Section titled “Try it”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.