# Is there a better way to loop n times?

I need to repeat some code for special times, now I’m using following code:

``````for i in 0..n {
// some code
}
``````

but it’s a little annoying because i don’t need `i` in my code and ‘0’ means nothing to me.
is there a better way to do this? Someting like this

``````loop n {

}

// or
loop!(n, {})
``````
3 Likes
``````for _ in 0..n { ... }
``````

It’s not that much more to type. If you really, desperately cannot stand typing four extra tokens, define a `loop!` macro.

11 Likes

is there any extra cost on boundary check using `for`?
Actually, what I mean is to repeat some code.

``````println!("some code");
println!("some code");
println!("some code");
// code above can fold as
loop 3 {
println!("come code");
};
``````

And what more important is it’s more clear than `for` .
@DanielKeep Can I achive this by define `loop!` macro? as I know macro cannot capture `n` then repeat special times.

Isn’t that what all loops are for? How is your loop different?

2 Likes

Every kind of finite loop has boundary checks.

There’s no static unrolling. That’s an optimisation LLVM will do if it feels it’s necessary.

If `n` is an actual literal, you could do it with a proc macro (which I don’t believe are stabilised in function form yet). If it’s not a literal, you can’t do it.

Just use a `for` loop unless you can demonstrate that it’s actually an issue.

2 Likes

I have already know how many times i need to repeat, so I don’t want boundary check.
And, I think `for i in 0..n` is not clear enough to express repeat n times. For example `for i in 1..n+1` do the same thing but express different meaning.

yes, I understand. thanks a lot.

This doesn’t make any sense to me… I still don’t understand how your loop is somehow special and not like any other loop.

In C, if I wanted to `printf` “jump” 10 times, I would code:

``````size_t i;
for(i = 0; i < 10; i++)
{
printf("Jump\n");
}
``````

Here, I know that I want to print “Jump” 10 times… I still have to specify 0-9 aka `i < 10`. That’s just how programming works. Alternatively, I could specify:

``````size_t i;
while(i < 10)
{
printf("Jump\n");
i++;
}
``````

Same thing, really. How else can I print jump 10 times aside from either writing a recursive solution or just copy/pasting `printf("Jump\n");` into the source-code 10 times???

Sure, I could `#define` some macro which just pastes `printf` 10 times, but what’s the point?

I'm not sure why this is an issue, and I'd just go with @DanielKeep's suggestions since it's pretty canonical and readable in rust. But just as a basic Rust exercise, here are a couple ways to not care about `0..n` vs `1..n+1`.

The `loopn!` (`loop` is a keyword) you asked for:

``````macro_rules! loopn {
(\$n:expr, \$body:block) => {
for _ in 0..\$n {
\$body
}
}
}
``````

Alternatively, a helper function supporting an iterator-based approach:

``````fn times(n: usize) -> impl Iterator {
std::iter::repeat(()).take(n)
}

fn main() {
for _ in times(5) {
println!("Hello world!");
}
}
``````

Both can be seen in this playground.

5 Likes

I second the comment to check whether this is actually an issue, but you can unroll constant loops with crunchy.

https://crates.io/crates/crunchy

1 Like

I see `1..n+1`, but no one has mentioned the inclusive-range operator as an alternative: `1..=n`. Stable since Rust 1.26.

3 Likes

because it looks ugly.

2 Likes

I strongly encourage getting used to `..`'s half-openness – it’s far better in algorithms because it splits elegantly: if you divide `low..high` into `low..mid` and `mid..high`, you have all the same items with no overlap and no error-prone `±1` adjustments. This has been known since at least 1982: https://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/EWD831.html

6 Likes

I was offering the inclusive range as an alternative to adding 1 on both sides. Personally, I wouldn’t add 1 in the first place, and would stick to the exclusive range.