| ... | ... | @@ -616,6 +616,17 @@ test "init with undefined" { |
| 616 | 616 | assert(x == 1); |
| 617 | 617 | } |
| 618 | 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 | 630 | {#header_close#} |
| 620 | 631 | {#header_close#} |
| 621 | 632 | {#header_close#} |
| ... | ... | @@ -2237,21 +2248,28 @@ test "switch inside function" { |
| 2237 | 2248 | {#see_also|comptime|enum|@compileError|Compile Variables#} |
| 2238 | 2249 | {#header_close#} |
| 2239 | 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 | 2255 | {#code_begin|test|while#} |
| 2241 | 2256 | const assert = @import("std").debug.assert; |
| 2242 | 2257 | |
| 2243 | 2258 | test "while basic" { |
| 2244 | | // A while loop is used to repeatedly execute an expression until |
| 2245 | | // some condition is no longer true. |
| 2246 | 2259 | var i: usize = 0; |
| 2247 | 2260 | while (i < 10) { |
| 2248 | 2261 | i += 1; |
| 2249 | 2262 | } |
| 2250 | 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 | 2272 | test "while break" { |
| 2254 | | // You can use break to exit a while loop early. |
| 2255 | 2273 | var i: usize = 0; |
| 2256 | 2274 | while (true) { |
| 2257 | 2275 | if (i == 10) |
| ... | ... | @@ -2260,9 +2278,14 @@ test "while break" { |
| 2260 | 2278 | } |
| 2261 | 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 | 2288 | test "while continue" { |
| 2265 | | // You can use continue to jump back to the beginning of the loop. |
| 2266 | 2289 | var i: usize = 0; |
| 2267 | 2290 | while (true) { |
| 2268 | 2291 | i += 1; |
| ... | ... | @@ -2272,18 +2295,21 @@ test "while continue" { |
| 2272 | 2295 | } |
| 2273 | 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 | 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 | 2307 | var i: usize = 0; |
| 2280 | 2308 | while (i < 10) : (i += 1) {} |
| 2281 | 2309 | assert(i == 10); |
| 2282 | 2310 | } |
| 2283 | 2311 | |
| 2284 | 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 | 2313 | var i1: usize = 1; |
| 2288 | 2314 | var j1: usize = 1; |
| 2289 | 2315 | while (i1 * j1 < 2000) : ({ i1 *= 2; j1 *= 3; }) { |
| ... | ... | @@ -2291,6 +2317,20 @@ test "while loop continuation expression, more complicated" { |
| 2291 | 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 | 2335 | test "while else" { |
| 2296 | 2336 | assert(rangeHasNumber(0, 10, 5)); |
| ... | ... | @@ -2299,24 +2339,31 @@ test "while else" { |
| 2299 | 2339 | |
| 2300 | 2340 | fn rangeHasNumber(begin: usize, end: usize, number: usize) bool { |
| 2301 | 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 | 2342 | return while (i < end) : (i += 1) { |
| 2306 | 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 | 2344 | break true; |
| 2312 | 2345 | } |
| 2313 | 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 | 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 | 2367 | var sum1: u32 = 0; |
| 2321 | 2368 | numbers_left = 3; |
| 2322 | 2369 | while (eventuallyNullSequence()) |value| { |
| ... | ... | @@ -2324,8 +2371,6 @@ test "while null capture" { |
| 2324 | 2371 | } |
| 2325 | 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 | 2374 | var sum2: u32 = 0; |
| 2330 | 2375 | numbers_left = 3; |
| 2331 | 2376 | while (eventuallyNullSequence()) |value| { |
| ... | ... | @@ -2333,18 +2378,6 @@ test "while null capture" { |
| 2333 | 2378 | } else { |
| 2334 | 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 | 2383 | var numbers_left: u32 = undefined; |
| ... | ... | @@ -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 | 2420 | fn eventuallyErrorSequence() error!u32 { |
| 2359 | 2421 | return if (numbers_left == 0) error.ReachedZero else blk: { |
| 2360 | 2422 | numbers_left -= 1; |
| ... | ... | @@ -2362,6 +2424,7 @@ fn eventuallyErrorSequence() error!u32 { |
| 2362 | 2424 | }; |
| 2363 | 2425 | } |
| 2364 | 2426 | {#code_end#} |
| 2427 | {#header_close#} |
| 2365 | 2428 | |
| 2366 | 2429 | {#header_open|inline while#} |
| 2367 | 2430 | <p> |