From 52c33804af9c85121fe8b65166e11ac2d1feee97 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Tue, 9 May 2017 12:30:26 +0100 Subject: [PATCH 1/5] loop_break_value: add documentation for book --- .../src/language-features/loop-break-value.md | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/src/doc/unstable-book/src/language-features/loop-break-value.md b/src/doc/unstable-book/src/language-features/loop-break-value.md index 54d6e62ce4c5..23527cfe8bd9 100644 --- a/src/doc/unstable-book/src/language-features/loop-break-value.md +++ b/src/doc/unstable-book/src/language-features/loop-break-value.md @@ -4,7 +4,89 @@ The tracking issue for this feature is: [#37339] [#37339]: https://github.com/rust-lang/rust/issues/37339 +Documentation to be appended to section 3.6 of the book: Loops (after "Loop Labels", or before if +the "Break" section is moved). If this is deemed too complex a feature this early in the book, it +could also be moved to a new section (please advise). This would allow examples breaking with +non-primitive types, references, and discussion of coercion (probably unnecessary however). + ------------------------ +### Loops as expressions + +Like everything else in Rust, loops are expressions; for example, the following is perfectly legal, +if rather useless: + +```rust +let result = for n in 1..4 { + println!("Hello, {}", n); +}; +assert_eq!(result, ()); +``` + +Until now, all the loops you have seen evaluate to either `()` or `!`, the latter being special +syntax for "no value", meaning the loop never exits. A `loop` can instead evaluate to +a useful value via *break with value*: + +```rust +// Find the first square number over 1000: +let mut n = 1; +let square = loop { + if n * n > 1000 { + break n * n; + } + n += 1; +}; +``` + +The evaluation type may be specified externally: + +```rust +// Declare that value returned is unsigned 64-bit: +let n: u64 = loop { + break 1; +}; +``` + +It is an error if types do not agree, either between a "break" value and an external requirement, +or between multiple "break" values: + +```rust +loop { + if random_bool() { + break 1u32; + } else { + break 0u8; // error: types do not agree + } +}; + +let n: i32 = loop { + break 0u32; // error: type does not agree with external requirement +}; +``` + +For now, breaking with a value is only possible with `loop`; the same functionality may +some day be added to `for` and `while` (this would require some new syntax like +`while f() { break 1; } default { break 0; }`). + +#### Break: label, value + +Four forms of `break` are available, where EXPR is some expression which evaluates to a value: + +1. `break;` +2. `break 'label;` +3. `break EXPR;` +4. `break 'label EXPR;` + +When no value is given, the value `()` is assumed, thus `break;` is equivalent to `break ();`. +Using a label allows returning a value from an inner loop: +```rust +let result = 'outer: loop { + for n in 1..10 { + if n > 4 { + break 'outer n; + } + } +}; +``` From 7d94b4804a51ec7da42ddf3ff4a6bed0518319f7 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Tue, 9 May 2017 15:48:45 +0100 Subject: [PATCH 2/5] loop_break_value: address review comments on book addition --- .../src/language-features/loop-break-value.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/doc/unstable-book/src/language-features/loop-break-value.md b/src/doc/unstable-book/src/language-features/loop-break-value.md index 23527cfe8bd9..dae04d737b78 100644 --- a/src/doc/unstable-book/src/language-features/loop-break-value.md +++ b/src/doc/unstable-book/src/language-features/loop-break-value.md @@ -4,16 +4,13 @@ The tracking issue for this feature is: [#37339] [#37339]: https://github.com/rust-lang/rust/issues/37339 -Documentation to be appended to section 3.6 of the book: Loops (after "Loop Labels", or before if -the "Break" section is moved). If this is deemed too complex a feature this early in the book, it -could also be moved to a new section (please advise). This would allow examples breaking with -non-primitive types, references, and discussion of coercion (probably unnecessary however). +Documentation to be appended to section G of the book. ------------------------ ### Loops as expressions -Like everything else in Rust, loops are expressions; for example, the following is perfectly legal, +Like most things in Rust, loops are expressions; for example, the following is perfectly legal, if rather useless: ```rust From 7488ff5c44f8e7515aa68e43011784de0893a6a6 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Tue, 9 May 2017 19:34:00 +0100 Subject: [PATCH 3/5] loop_break_value book doc: remove some curiosities, regarding leodasvacas's comments --- .../src/language-features/loop-break-value.md | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/doc/unstable-book/src/language-features/loop-break-value.md b/src/doc/unstable-book/src/language-features/loop-break-value.md index dae04d737b78..7218cad1c228 100644 --- a/src/doc/unstable-book/src/language-features/loop-break-value.md +++ b/src/doc/unstable-book/src/language-features/loop-break-value.md @@ -10,19 +10,9 @@ Documentation to be appended to section G of the book. ### Loops as expressions -Like most things in Rust, loops are expressions; for example, the following is perfectly legal, -if rather useless: - -```rust -let result = for n in 1..4 { - println!("Hello, {}", n); -}; -assert_eq!(result, ()); -``` - -Until now, all the loops you have seen evaluate to either `()` or `!`, the latter being special -syntax for "no value", meaning the loop never exits. A `loop` can instead evaluate to -a useful value via *break with value*: +Like most things in Rust, loops are expressions, and have a value; normally `()` unless the loop +never exits. +A `loop` can instead evaluate to a useful value via *break with value*: ```rust // Find the first square number over 1000: From 3f980beb3eeb545ff9de7f3976beb7872b4e2ae6 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Tue, 16 May 2017 18:54:41 +0100 Subject: [PATCH 4/5] loop_break_value: fix tests (but ignore one expected not to compile) --- .../src/language-features/loop-break-value.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/doc/unstable-book/src/language-features/loop-break-value.md b/src/doc/unstable-book/src/language-features/loop-break-value.md index 7218cad1c228..9e36ea7b1a76 100644 --- a/src/doc/unstable-book/src/language-features/loop-break-value.md +++ b/src/doc/unstable-book/src/language-features/loop-break-value.md @@ -15,6 +15,8 @@ never exits. A `loop` can instead evaluate to a useful value via *break with value*: ```rust +#![feature(loop_break_value)] + // Find the first square number over 1000: let mut n = 1; let square = loop { @@ -28,6 +30,8 @@ let square = loop { The evaluation type may be specified externally: ```rust +#![feature(loop_break_value)] + // Declare that value returned is unsigned 64-bit: let n: u64 = loop { break 1; @@ -37,9 +41,11 @@ let n: u64 = loop { It is an error if types do not agree, either between a "break" value and an external requirement, or between multiple "break" values: -```rust +```no_compile +#![feature(loop_break_value)] + loop { - if random_bool() { + if true { break 1u32; } else { break 0u8; // error: types do not agree @@ -69,6 +75,8 @@ When no value is given, the value `()` is assumed, thus `break;` is equivalent t Using a label allows returning a value from an inner loop: ```rust +#![feature(loop_break_value)] + let result = 'outer: loop { for n in 1..10 { if n > 4 { From 7ab35b703a2213eba91cadcad90aefa169f48f1f Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Wed, 17 May 2017 13:00:10 +0100 Subject: [PATCH 5/5] loop_break_value doc: remove note about other loops --- .../unstable-book/src/language-features/loop-break-value.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/doc/unstable-book/src/language-features/loop-break-value.md b/src/doc/unstable-book/src/language-features/loop-break-value.md index 9e36ea7b1a76..e8fefe3b7334 100644 --- a/src/doc/unstable-book/src/language-features/loop-break-value.md +++ b/src/doc/unstable-book/src/language-features/loop-break-value.md @@ -57,10 +57,6 @@ let n: i32 = loop { }; ``` -For now, breaking with a value is only possible with `loop`; the same functionality may -some day be added to `for` and `while` (this would require some new syntax like -`while f() { break 1; } default { break 0; }`). - #### Break: label, value Four forms of `break` are available, where EXPR is some expression which evaluates to a value: