| ... | @@ -2355,11 +2355,18 @@ fn eventuallyErrorSequence() error!u32 { | ... | @@ -2355,11 +2355,18 @@ fn eventuallyErrorSequence() error!u32 { |
| 2355 | break :blk numbers_left; | 2355 | break :blk numbers_left; |
| 2356 | }; | 2356 | }; |
| 2357 | } | 2357 | } |
| | 2358 | {#code_end#} |
| | 2359 | |
| | 2360 | {#header_open|inline while#} |
| | 2361 | <p> |
| | 2362 | While loops can be inlined. This causes the loop to be unrolled, which |
| | 2363 | allows the code to do some things which only work at compile time, |
| | 2364 | such as use types as first class values. |
| | 2365 | </p> |
| | 2366 | {#code_begin|test#} |
| | 2367 | const assert = @import("std").debug.assert; |
| 2358 | | 2368 | |
| 2359 | test "inline while loop" { | 2369 | test "inline while loop" { |
| 2360 | // While loops can be inlined. This causes the loop to be unrolled, which | | |
| 2361 | // allows the code to do some things which only work at compile time, | | |
| 2362 | // such as use types as first class values. | | |
| 2363 | comptime var i = 0; | 2370 | comptime var i = 0; |
| 2364 | var sum: usize = 0; | 2371 | var sum: usize = 0; |
| 2365 | inline while (i < 3) : (i += 1) { | 2372 | inline while (i < 3) : (i += 1) { |
| ... | @@ -2378,6 +2385,16 @@ fn typeNameLength(comptime T: type) usize { | ... | @@ -2378,6 +2385,16 @@ fn typeNameLength(comptime T: type) usize { |
| 2378 | return @typeName(T).len; | 2385 | return @typeName(T).len; |
| 2379 | } | 2386 | } |
| 2380 | {#code_end#} | 2387 | {#code_end#} |
| | 2388 | <p> |
| | 2389 | It is recommended to use <code>inline</code> loops only for one of these reasons: |
| | 2390 | </p> |
| | 2391 | <ul> |
| | 2392 | <li>You need the loop to execute at {#link|comptime#} for the semantics to work.</li> |
| | 2393 | <li> |
| | 2394 | You have a benchmark to prove that forcibly unrolling the loop in this way is measurably faster. |
| | 2395 | </li> |
| | 2396 | </ul> |
| | 2397 | {#header_close#} |
| 2381 | {#see_also|if|Optionals|Errors|comptime|unreachable#} | 2398 | {#see_also|if|Optionals|Errors|comptime|unreachable#} |
| 2382 | {#header_close#} | 2399 | {#header_close#} |
| 2383 | {#header_open|for#} | 2400 | {#header_open|for#} |
| ... | @@ -2445,15 +2462,20 @@ test "for else" { | ... | @@ -2445,15 +2462,20 @@ test "for else" { |
| 2445 | break :blk sum; | 2462 | break :blk sum; |
| 2446 | }; | 2463 | }; |
| 2447 | } | 2464 | } |
| 2448 | | 2465 | {#code_end#} |
| | 2466 | {#header_open|inline for#} |
| | 2467 | <p> |
| | 2468 | For loops can be inlined. This causes the loop to be unrolled, which |
| | 2469 | allows the code to do some things which only work at compile time, |
| | 2470 | such as use types as first class values. |
| | 2471 | The capture value and iterator value of inlined for loops are |
| | 2472 | compile-time known. |
| | 2473 | </p> |
| | 2474 | {#code_begin|test#} |
| | 2475 | const assert = @import("std").debug.assert; |
| 2449 | | 2476 | |
| 2450 | test "inline for loop" { | 2477 | test "inline for loop" { |
| 2451 | const nums = []i32{2, 4, 6}; | 2478 | const nums = []i32{2, 4, 6}; |
| 2452 | // For loops can be inlined. This causes the loop to be unrolled, which | | |
| 2453 | // allows the code to do some things which only work at compile time, | | |
| 2454 | // such as use types as first class values. | | |
| 2455 | // The capture value and iterator value of inlined for loops are | | |
| 2456 | // compile-time known. | | |
| 2457 | var sum: usize = 0; | 2479 | var sum: usize = 0; |
| 2458 | inline for (nums) |i| { | 2480 | inline for (nums) |i| { |
| 2459 | const T = switch (i) { | 2481 | const T = switch (i) { |
| ... | @@ -2471,6 +2493,16 @@ fn typeNameLength(comptime T: type) usize { | ... | @@ -2471,6 +2493,16 @@ fn typeNameLength(comptime T: type) usize { |
| 2471 | return @typeName(T).len; | 2493 | return @typeName(T).len; |
| 2472 | } | 2494 | } |
| 2473 | {#code_end#} | 2495 | {#code_end#} |
| | 2496 | <p> |
| | 2497 | It is recommended to use <code>inline</code> loops only for one of these reasons: |
| | 2498 | </p> |
| | 2499 | <ul> |
| | 2500 | <li>You need the loop to execute at {#link|comptime#} for the semantics to work.</li> |
| | 2501 | <li> |
| | 2502 | You have a benchmark to prove that forcibly unrolling the loop in this way is measurably faster. |
| | 2503 | </li> |
| | 2504 | </ul> |
| | 2505 | {#header_close#} |
| 2474 | {#see_also|while|comptime|Arrays|Slices#} | 2506 | {#see_also|while|comptime|Arrays|Slices#} |
| 2475 | {#header_close#} | 2507 | {#header_close#} |
| 2476 | {#header_open|if#} | 2508 | {#header_open|if#} |
| ... | @@ -4222,13 +4254,8 @@ pub fn main() void { | ... | @@ -4222,13 +4254,8 @@ pub fn main() void { |
| 4222 | task in userland. It does so without introducing another language on top of Zig, such as | 4254 | task in userland. It does so without introducing another language on top of Zig, such as |
| 4223 | a macro language or a preprocessor language. It's Zig all the way down. | 4255 | a macro language or a preprocessor language. It's Zig all the way down. |
| 4224 | </p> | 4256 | </p> |
| 4225 | <p>TODO: suggestion to not use inline unless necessary</p> | | |
| 4226 | {#header_close#} | | |
| 4227 | {#header_close#} | 4257 | {#header_close#} |
| 4228 | {#header_open|inline#} | 4258 | {#see_also|inline while|inline for#} |
| 4229 | <p>TODO: inline while</p> | | |
| 4230 | <p>TODO: inline for</p> | | |
| 4231 | <p>TODO: suggestion to not use inline unless necessary</p> | | |
| 4232 | {#header_close#} | 4259 | {#header_close#} |
| 4233 | {#header_open|Assembly#} | 4260 | {#header_open|Assembly#} |
| 4234 | <p>TODO: example of inline assembly</p> | 4261 | <p>TODO: example of inline assembly</p> |