| ... | @@ -616,6 +616,17 @@ test "init with undefined" { | ... | @@ -616,6 +616,17 @@ test "init with undefined" { |
| 616 | assert(x == 1); | 616 | assert(x == 1); |
| 617 | } | 617 | } |
| 618 | {#code_end#} | 618 | {#code_end#} |
| | 619 | <p> |
| | 620 | <code>undefined</code> can be {#link|implicitly cast|Implicit Casts#} to any type. |
| | 621 | Once this happens, it is no longer possible to detect that the value is <code>undefined</code>. |
| | 622 | <code>undefined</code> means the value could be anything, even something that is nonsense |
| | 623 | according to the type. Translated into English, <code>undefined</code> means "Not a meaningful |
| | 624 | value. Using this value would be a bug. The value will be unused, or overwritten before being used." |
| | 625 | </p> |
| | 626 | <p> |
| | 627 | In {#link|Debug#} mode, Zig writes <code>0xaa</code> bytes to undefined memory. This is to catch |
| | 628 | bugs early, and to help detect use of undefined memory in a debugger. |
| | 629 | </p> |
| 619 | {#header_close#} | 630 | {#header_close#} |
| 620 | {#header_close#} | 631 | {#header_close#} |
| 621 | {#header_close#} | 632 | {#header_close#} |
| ... | @@ -2237,21 +2248,28 @@ test "switch inside function" { | ... | @@ -2237,21 +2248,28 @@ test "switch inside function" { |
| 2237 | {#see_also|comptime|enum|@compileError|Compile Variables#} | 2248 | {#see_also|comptime|enum|@compileError|Compile Variables#} |
| 2238 | {#header_close#} | 2249 | {#header_close#} |
| 2239 | {#header_open|while#} | 2250 | {#header_open|while#} |
| | 2251 | <p> |
| | 2252 | A while loop is used to repeatedly execute an expression until |
| | 2253 | some condition is no longer true. |
| | 2254 | </p> |
| 2240 | {#code_begin|test|while#} | 2255 | {#code_begin|test|while#} |
| 2241 | const assert = @import("std").debug.assert; | 2256 | const assert = @import("std").debug.assert; |
| 2242 | | 2257 | |
| 2243 | test "while basic" { | 2258 | test "while basic" { |
| 2244 | // A while loop is used to repeatedly execute an expression until | | |
| 2245 | // some condition is no longer true. | | |
| 2246 | var i: usize = 0; | 2259 | var i: usize = 0; |
| 2247 | while (i < 10) { | 2260 | while (i < 10) { |
| 2248 | i += 1; | 2261 | i += 1; |
| 2249 | } | 2262 | } |
| 2250 | assert(i == 10); | 2263 | assert(i == 10); |
| 2251 | } | 2264 | } |
| | 2265 | {#code_end#} |
| | 2266 | <p> |
| | 2267 | Use <code>break</code> to exit a while loop early. |
| | 2268 | </p> |
| | 2269 | {#code_begin|test|while#} |
| | 2270 | const assert = @import("std").debug.assert; |
| 2252 | | 2271 | |
| 2253 | test "while break" { | 2272 | test "while break" { |
| 2254 | // You can use break to exit a while loop early. | | |
| 2255 | var i: usize = 0; | 2273 | var i: usize = 0; |
| 2256 | while (true) { | 2274 | while (true) { |
| 2257 | if (i == 10) | 2275 | if (i == 10) |
| ... | @@ -2260,9 +2278,14 @@ test "while break" { | ... | @@ -2260,9 +2278,14 @@ test "while break" { |
| 2260 | } | 2278 | } |
| 2261 | assert(i == 10); | 2279 | assert(i == 10); |
| 2262 | } | 2280 | } |
| | 2281 | {#code_end#} |
| | 2282 | <p> |
| | 2283 | Use <code>continue</code> to jump back to the beginning of the loop. |
| | 2284 | </p> |
| | 2285 | {#code_begin|test|while#} |
| | 2286 | const assert = @import("std").debug.assert; |
| 2263 | | 2287 | |
| 2264 | test "while continue" { | 2288 | test "while continue" { |
| 2265 | // You can use continue to jump back to the beginning of the loop. | | |
| 2266 | var i: usize = 0; | 2289 | var i: usize = 0; |
| 2267 | while (true) { | 2290 | while (true) { |
| 2268 | i += 1; | 2291 | i += 1; |
| ... | @@ -2272,18 +2295,21 @@ test "while continue" { | ... | @@ -2272,18 +2295,21 @@ test "while continue" { |
| 2272 | } | 2295 | } |
| 2273 | assert(i == 10); | 2296 | assert(i == 10); |
| 2274 | } | 2297 | } |
| | 2298 | {#code_end#} |
| | 2299 | <p> |
| | 2300 | While loops support a continue expression which is executed when the loop |
| | 2301 | is continued. The <code>continue</code> keyword respects this expression. |
| | 2302 | </p> |
| | 2303 | {#code_begin|test|while#} |
| | 2304 | const assert = @import("std").debug.assert; |
| 2275 | | 2305 | |
| 2276 | test "while loop continuation expression" { | 2306 | test "while loop continuation expression" { |
| 2277 | // You can give an expression to the while loop to execute when | | |
| 2278 | // the loop is continued. This is respected by the continue control flow. | | |
| 2279 | var i: usize = 0; | 2307 | var i: usize = 0; |
| 2280 | while (i < 10) : (i += 1) {} | 2308 | while (i < 10) : (i += 1) {} |
| 2281 | assert(i == 10); | 2309 | assert(i == 10); |
| 2282 | } | 2310 | } |
| 2283 | | 2311 | |
| 2284 | test "while loop continuation expression, more complicated" { | 2312 | test "while loop continuation expression, more complicated" { |
| 2285 | // More complex blocks can be used as an expression in the loop continue | | |
| 2286 | // expression. | | |
| 2287 | var i1: usize = 1; | 2313 | var i1: usize = 1; |
| 2288 | var j1: usize = 1; | 2314 | var j1: usize = 1; |
| 2289 | while (i1 * j1 < 2000) : ({ i1 *= 2; j1 *= 3; }) { | 2315 | while (i1 * j1 < 2000) : ({ i1 *= 2; j1 *= 3; }) { |
| ... | @@ -2291,6 +2317,20 @@ test "while loop continuation expression, more complicated" { | ... | @@ -2291,6 +2317,20 @@ test "while loop continuation expression, more complicated" { |
| 2291 | assert(my_ij1 < 2000); | 2317 | assert(my_ij1 < 2000); |
| 2292 | } | 2318 | } |
| 2293 | } | 2319 | } |
| | 2320 | {#code_end#} |
| | 2321 | <p> |
| | 2322 | While loops are expressions. The result of the expression is the |
| | 2323 | result of the <code>else</code> clause of a while loop, which is executed when |
| | 2324 | the condition of the while loop is tested as false. |
| | 2325 | </p> |
| | 2326 | <p> |
| | 2327 | <code>break</code>, like <code>return</code>, accepts a value |
| | 2328 | parameter. This is the result of the <code>while</code> expression. |
| | 2329 | When you <code>break</code> from a while loop, the <code>else</code> branch is not |
| | 2330 | evaluated. |
| | 2331 | </p> |
| | 2332 | {#code_begin|test|while#} |
| | 2333 | const assert = @import("std").debug.assert; |
| 2294 | | 2334 | |
| 2295 | test "while else" { | 2335 | test "while else" { |
| 2296 | assert(rangeHasNumber(0, 10, 5)); | 2336 | assert(rangeHasNumber(0, 10, 5)); |
| ... | @@ -2299,24 +2339,31 @@ test "while else" { | ... | @@ -2299,24 +2339,31 @@ test "while else" { |
| 2299 | | 2339 | |
| 2300 | fn rangeHasNumber(begin: usize, end: usize, number: usize) bool { | 2340 | fn rangeHasNumber(begin: usize, end: usize, number: usize) bool { |
| 2301 | var i = begin; | 2341 | var i = begin; |
| 2302 | // While loops are expressions. The result of the expression is the | | |
| 2303 | // result of the else clause of a while loop, which is executed when | | |
| 2304 | // the condition of the while loop is tested as false. | | |
| 2305 | return while (i < end) : (i += 1) { | 2342 | return while (i < end) : (i += 1) { |
| 2306 | if (i == number) { | 2343 | if (i == number) { |
| 2307 | // break expressions, like return expressions, accept a value | | |
| 2308 | // parameter. This is the result of the while expression. | | |
| 2309 | // When you break from a while loop, the else branch is not | | |
| 2310 | // evaluated. | | |
| 2311 | break true; | 2344 | break true; |
| 2312 | } | 2345 | } |
| 2313 | } else false; | 2346 | } else false; |
| 2314 | } | 2347 | } |
| | 2348 | {#code_end#} |
| | 2349 | {#header_open|while with Optionals#} |
| | 2350 | <p> |
| | 2351 | Just like {#link|if#} expressions, while loops can take an optional as the |
| | 2352 | condition and capture the payload. When {#link|null#} is encountered the loop |
| | 2353 | exits. |
| | 2354 | </p> |
| | 2355 | <p> |
| | 2356 | When the <code>|x|</code> syntax is present on a <code>while</code> expression, |
| | 2357 | the while condition must have an {#link|Optional Type#}. |
| | 2358 | </p> |
| | 2359 | <p> |
| | 2360 | The <code>else</code> branch is allowed on optional iteration. In this case, it will |
| | 2361 | be executed on the first null value encountered. |
| | 2362 | </p> |
| | 2363 | {#code_begin|test|while#} |
| | 2364 | const assert = @import("std").debug.assert; |
| 2315 | | 2365 | |
| 2316 | test "while null capture" { | 2366 | test "while null capture" { |
| 2317 | // Just like if expressions, while loops can take an optional as the | | |
| 2318 | // condition and capture the payload. When null is encountered the loop | | |
| 2319 | // exits. | | |
| 2320 | var sum1: u32 = 0; | 2367 | var sum1: u32 = 0; |
| 2321 | numbers_left = 3; | 2368 | numbers_left = 3; |
| 2322 | while (eventuallyNullSequence()) |value| { | 2369 | while (eventuallyNullSequence()) |value| { |
| ... | @@ -2324,8 +2371,6 @@ test "while null capture" { | ... | @@ -2324,8 +2371,6 @@ test "while null capture" { |
| 2324 | } | 2371 | } |
| 2325 | assert(sum1 == 3); | 2372 | assert(sum1 == 3); |
| 2326 | | 2373 | |
| 2327 | // The else branch is allowed on optional iteration. In this case, it will | | |
| 2328 | // be executed on the first null value encountered. | | |
| 2329 | var sum2: u32 = 0; | 2374 | var sum2: u32 = 0; |
| 2330 | numbers_left = 3; | 2375 | numbers_left = 3; |
| 2331 | while (eventuallyNullSequence()) |value| { | 2376 | while (eventuallyNullSequence()) |value| { |
| ... | @@ -2333,18 +2378,6 @@ test "while null capture" { | ... | @@ -2333,18 +2378,6 @@ test "while null capture" { |
| 2333 | } else { | 2378 | } else { |
| 2334 | assert(sum1 == 3); | 2379 | assert(sum1 == 3); |
| 2335 | } | 2380 | } |
| 2336 | | | |
| 2337 | // Just like if expressions, while loops can also take an error union as | | |
| 2338 | // the condition and capture the payload or the error code. When the | | |
| 2339 | // condition results in an error code the else branch is evaluated and | | |
| 2340 | // the loop is finished. | | |
| 2341 | var sum3: u32 = 0; | | |
| 2342 | numbers_left = 3; | | |
| 2343 | while (eventuallyErrorSequence()) |value| { | | |
| 2344 | sum3 += value; | | |
| 2345 | } else |err| { | | |
| 2346 | assert(err == error.ReachedZero); | | |
| 2347 | } | | |
| 2348 | } | 2381 | } |
| 2349 | | 2382 | |
| 2350 | var numbers_left: u32 = undefined; | 2383 | var numbers_left: u32 = undefined; |
| ... | @@ -2355,6 +2388,35 @@ fn eventuallyNullSequence() ?u32 { | ... | @@ -2355,6 +2388,35 @@ fn eventuallyNullSequence() ?u32 { |
| 2355 | }; | 2388 | }; |
| 2356 | } | 2389 | } |
| 2357 | | 2390 | |
| | 2391 | {#code_end#} |
| | 2392 | {#header_close#} |
| | 2393 | |
| | 2394 | {#header_open|while with Error Unions#} |
| | 2395 | <p> |
| | 2396 | Just like {#link|if#} expressions, while loops can take an error union as |
| | 2397 | the condition and capture the payload or the error code. When the |
| | 2398 | condition results in an error code the else branch is evaluated and |
| | 2399 | the loop is finished. |
| | 2400 | </p> |
| | 2401 | <p> |
| | 2402 | When the <code>else |x|</code> syntax is present on a <code>while</code> expression, |
| | 2403 | the while condition must have an {#link|Error Union Type#}. |
| | 2404 | </p> |
| | 2405 | {#code_begin|test|while#} |
| | 2406 | const assert = @import("std").debug.assert; |
| | 2407 | |
| | 2408 | test "while error union capture" { |
| | 2409 | var sum1: u32 = 0; |
| | 2410 | numbers_left = 3; |
| | 2411 | while (eventuallyErrorSequence()) |value| { |
| | 2412 | sum1 += value; |
| | 2413 | } else |err| { |
| | 2414 | assert(err == error.ReachedZero); |
| | 2415 | } |
| | 2416 | } |
| | 2417 | |
| | 2418 | var numbers_left: u32 = undefined; |
| | 2419 | |
| 2358 | fn eventuallyErrorSequence() error!u32 { | 2420 | fn eventuallyErrorSequence() error!u32 { |
| 2359 | return if (numbers_left == 0) error.ReachedZero else blk: { | 2421 | return if (numbers_left == 0) error.ReachedZero else blk: { |
| 2360 | numbers_left -= 1; | 2422 | numbers_left -= 1; |
| ... | @@ -2362,6 +2424,7 @@ fn eventuallyErrorSequence() error!u32 { | ... | @@ -2362,6 +2424,7 @@ fn eventuallyErrorSequence() error!u32 { |
| 2362 | }; | 2424 | }; |
| 2363 | } | 2425 | } |
| 2364 | {#code_end#} | 2426 | {#code_end#} |
| | 2427 | {#header_close#} |
| 2365 | | 2428 | |
| 2366 | {#header_open|inline while#} | 2429 | {#header_open|inline while#} |
| 2367 | <p> | 2430 | <p> |