Inclusive ranges only work in switch block and non-inclusive ranges only work in for loops. What not both for both?

const std = @import("std");

pub fn main() !void {
    const n: u8 = 1;
    switch (n) {
        0..5 => // error
            std.debug.print("matched\n", .{}),
        6...9 => // okay
            {},
        else => {},
    }
    
    for (0..5) // okay
        |i| std.debug.print("{}\n", .{i});
    
    for (0...5) // error
        |i| std.debug.print("{}\n", .{i});
}
2 Likes

When you iterate over a slice or an array, it’s common to start with 0 and end with len - 1, whereas you typically write in the switch prong only elements that are within the set you’re matching with.

I agree there should be ..= and ..< available for both though. I do find myself writing start_1...start_2 - 1 in a switch prong every once in a while. On the other hand, I’ve never had to use for (0..end + 1).

I find this quite strange too.
Both exclusive .. and inclusive ... should work in switches and slices and for loops in IMHO.

I’m glad it doesn’t.

I don’t want to collect a bunch of different ways to do something, and I don’t want to ponder which of those ways to do something would be most perfectly aesthetic for a given occasion.

I definitely don’t want to contemplate why someone else chose this one instead of that one, for this instance, and I never ever ever want to make a mistake which comes down to thinking I chose A when I actually chose B, or because I read B as A.

I just want to write code. ... is better for switches, because you aren’t forced to mention a value which can’t appear, .. is better for for, because for also takes slices, and that’s how slices work. for (slice[0..3]), three values, for (0...3), also three values.

It isn’t possible to gain expressive power by adding two ways to say the same thing, there’s nothing we can’t do now, which we could do if we had the exciting ability to write a new class of bug. So let’s not.

More visually distinctive, better on that basis, but doesn’t solve my main objection to having them in the first place.

Switching being exhaustive, that’s better IMHO:

   start_1...start_2 - 1 => { ... },
   start_2...final => { .. },

“The range from start_1 to just before start_2, and the range from start_2 to final”. It says what it does, that’s good.

Btw:

Did you notice that one { ... } was different from the other { .. }, until I said it? Be honest. Did you?[1]

Ok then. Let’s not make an important semantic distinction based on .. and ...! The reason those tokens are tolerable is that they can’t show up in the same place.

Edit: amusingly, the for(0...3)? Was just a typo. I’m leaving it in though.,.


  1. rhetorical! ↩︎

8 Likes