How to create a sequence of from,to,step

Hi, folk

I'm going through the usual process of trying to map the familiar to the novel, which in this case are R and Rust.

To create an array in Rust, there's

let my_array = [10, 20, 30, 40, 50];

and I would like to do that with some fn similarly to R, if it exists

my_array <- seq(10,50,10)

Searches for sequence yielded crates that I don't yet understand, which is ok, but they really don't seem on point to my search. If there's no native or crate that does this similarly to R::seq(), that's fine. I'll get to the point that I can roll my own someday. Just hoping to shortcut or spare the agony of a quest for what does not exist. Thx.

You can:

  1. Create a static array as: let my_array = [10, 20, 30, 40, 50];
  2. Create a vector as: let my_vec = vec![10, 20, 30, 40, 50];

I suspect you want the second.

I think the closest option is going to be something like

let my_vec: Vec<u32> = (10..=50).step_by(10).collect();
14 Likes

Ah right, I completely misunderstood the point.

If you create and array with

let my_array = [10, 20, 30, 40, 50];

I believe my_array goes on the stack but if you create a vector with

maybe my_vec gets stored on the heap?

2 Likes

No, that is not correct. Whether something goes on the stack or the heap is not determined by its type. Rather, it depends on how/where you store the value.

In particular, it is not the case that "arrays go on the stack" and "vectors go on the heap". A value always goes on the stack – regardless of its type – by default, when you declare it as an immediate local variable. There are collection/smart pointer types, however, which explicitly heap-allocate an internal buffer, and so they themselves store some other values on the heap (regardless of where the collection "handle" itself resides).

So for example:

// x is on the stack and so are its elements
let x = [1, 2, 3];

// y the Vec itself is on the stack,
// the buffer with its elements is on the heap
let y = vec![1, 2, 3];

// z is on the stack, the pointed array is on the heap,
// and the elements of the pointed array are on the heap
let z = Box::new([1, 2, 3]);

// the outer Vec is on the stack, the inner Vec
// is on the heap because it's in the outer Vec,
// and its elements are also on the heap
let w = vec![vec![1, 2, 3]];
5 Likes

Ok, that is some good details and thanks for details. I was being simple, but yes, the Vec is on the sttack, the storage is on the heap and that is the point I was directing at.

Can you clarify this

I though that the [1, 2, 3] would allocate an array on the stack and the Box::new() moved the data to the heap. Do I have that wrong in my brain?

Looking again at the subject title I realize the whole "array" or "vec" stack / heap is a sideways topic to creating a sequence. But thanks for answering anyways. :sunglasses:

Just like the whole "stack vs heap" distinction, this behavior is an implementation detail. What I was describing is the final layout of the value; whethet the compiler creates a temporary stack array is not something you should rely on (or worry about). It may or may not — the result is the same.

Thanks for the Rosetta Stone @stonerfish and thanks @H2CO3 for an insight that I will file away until I'm grown up enough to understand.

Credit where credit due @2e71828. Sorry I dropped the thread. This gives me insight that I needed--I will probably have to re-invent some wheels.

There's num::range_step() that will build the Vec without iterating over the intermediate values (update: Range step_by is clever enough to do this efficiently too, see below). It handles negative steps and is implemented pretty-much optimally.

use num::range_step;

fn main() {
    let my_array: Vec<u32> = range_step(10, 51, 10).collect();
    println!("{:?}", my_array);
}
1 Like

step_by() does the same. It uses .nth() under the hood, which is implemented on Range so that it doesn't naïvely iterate over the values to be skipped.

1 Like

Ah, good, thanks... I guess I should have checked before insinuating otherwise.