4 ms·
I have great hope for Zig. I agree with Andrew Kelley on most of the design decisions I've paid attention to. >for loop can only be used to iterate over elemen
by abainbridge 5y ago
I have great hope for Zig. I agree with Andrew Kelley on most of the design decisions I've paid attention to.
>for loop can only be used to iterate over elements of an array, if you want to just execute a block N times, you need while…
The Zig docs suggest something like this:
var i: usize = 0;
while (i < 10) {
i += 1;
}
Is there a plan to provide a mechanism to stop "i" from remaining in scope after the end of the loop? I couldn't find anything relevant with a quick web search.
I use integer iterating for-loops a lot in C. I just checked a 5000 line project of mine that deals with bitmaps. There are 100 occurrences of something like:
for (int i = 0; i < 10; i++) {
I think these would all become while-loops in Zig. Exposing 100 variables to a larger scope than they need to be sounds like a source of bugs to me.
- canadaduane 5y agoI'm new to Zig but I think this is how you would do it: { var i: usize = 0; while (i < 10) : (i += 1) { // use i } }
- tored 5y agoLooks like a solution, a bit annoying to introduce an extra block.
- abainbridge 5y agoYeah. And it fails the "make the easy way the right way" test of language design.
- dnautics 5y agoI give a c-like for loop (or while loop) a 40% odds of making it into the language. That number being pulled out of my nether regions.
- hiccuphippo 5y agoAs a hack, you can use an array of u0 to make simple loops: for ([1]u0{0} ** 10) |_, i| { std.debug.print("{d}", .{i}); }
- tored 5y agoNot a Zig programmer, but that looks horrible.
- AnIdiotOnTheNet 5y agoYeah, it's a hack. If you're doing it a lot you can abstract it into a function to clean it up: fn count(comptime n: usize) [n]u0 { return [1]u0{0} ** n; } for (count(10)) |_, i| { std.debug.print("{d}", .{i}); } or, if you don't need to capture the index: for (count(9)) |_| { //I can do it 9 times } Personally I've found I rarely need this kind of loop, so I just use the 'while' formulation because it is more obvious.
- dnautics 5y agoHah! i thought it was not a hack so much as a 'joke' that someone had discovered and posted to the discord, to much amusement. Are people actually using this? I will be amused when std.math.range shows up with this implementation.
- suby 5y agoIs there a performance penalty for this?
- dnautics 5y agosee for yourself: https://godbolt.org/z/Mj9T7vP44 https://godbolt.org/z/Mj9T7vP44
- hota_mazi 5y agoOf all the syntaxes I've seen to do this, I like Kotlin's best: repeat(10) { println("Counter is $it") } Kotlin optimizes nicely for the most default case while giving you flexibility if you need it (different parameter name, step, etc...).
- ncmncm 5y agoThere is of course { var i: usize = 0; while (i != 10) : (i += 1) { ... }} I.e., you are not obliged to plaster on a newline after every semicolon. That is roughly as busy as the equivalent C++ loop, for (auto i = 0u; i != 10; ++i) { ... } but syntax is syntax. You would be much better off with a function that takes a lambda, and pass the body as that lambda. In C++, a loop using that would look like forloop(10u, [&](auto i) { ... }); That's not a much shorter than the built-in, but leaves a lot less room for mistakes; i.e., if there was a typo in the built-in, it might be very hard to make yourself see it even knowing it must be there. I can't find anything to suggest Zig has lambdas. That's a planet-sized hole, nowadays. (BTW, forloop in C++ is just template <typename Ix, typename Body> void forloop(Ix top, Body&& body) { for (Ix i{}; i != top; ++i) body(i); } In use it compiles to instructions identical to the built-in loop.)
- pron 5y ago> I can't find anything to suggest Zig has lambdas. Closures are problematic in low-level languages, as their capture behaviour requires tricky syntax and/or implicitness, and Zig is very much opposed to both. Non-capturing anonymous functions expressions will be added (https://github.com/ziglang/zig/issues/1717 https://github.com/ziglang/zig/issues/1717), while a limited form of closure is being considered (https://github.com/ziglang/zig/issues/6965 https://github.com/ziglang/zig/issues/6965).
- kristoff_it 5y agoEven if we assume that this is a big problem, identifying it is the easy part, the harder part is coming up with a solution. If you just think about this specific issue, then it seems obvious that the solution should be to change the syntax to accommodate what other C-like languages are doing, but if you look at the language as a whole will see all the other problems that get introduced, making this change less straight forward than it might seem initially. My recommendation to the people that want to see this changed is to do the work to understand enough about Zig to be able to produce a proposal and see how that goes. There even are ~regular meetings where a guest can participate to present a proposal to the language design committee. That said, here's my take (just to clarify, I'm not part of the language design committee): I think it's fine as is and the solution is to just use blocks the right way. In other comments people showed the example of encapsulating a while loop in a block, but that's just an artificial example that I agree doesn't seem too convincing. The reality is that leaking a variable is not terribly bad per se, it only becomes bad when a function has a lot of things going on and also maybe multiple loops, like you mentioned here: > Exposing 100 variables to a larger scope than they need to be sounds like a source of bugs to me. My argument at this point is that if you have a function with multiple while loops and enough things going on that leaking a variable would be a problem, then you should have blocks in place already, which in other words means that it's not the while loop that needs to be artificially wrapped in a block to overcome a language limitation, but rather that the loop + its surrounding context should be wrapped in a very natural block regardless. Of course having the ability to use a while loop to restrict the lifetime of its index would be better, but what I mentioned just now about wrapping each context makes me think that it's not that bad of a problem and, on the other hand, the design problem I mentioned in the beginning makes me think, given what I know currently, that this might very well be a sweetspot despite the "common sense" complaints that people have.
- AndyKelley 5y agoEveryone thinks this is a problem because they are used to being allowed to shadow variables, and they've been bitten by variable shadowing, and they solved the problem by limiting the scope of the variable so as to reduce the likelihood of shadowing. But you can't make any mistake in Zig. If you tried to declare `i` later in the scope, you would get "error: redeclaration of `i`", which you could then solve with wrapping the mutable state in a scope. With no variable shadowing allowed, having many locals in scope is not a problem.