Review for: Remove C-style for-loops with conditions and incrementers

That's buggy (and also does not compile). What you want is this:

var i = 0
var first = true
while ({ () -> Bool in if first { first = false } else { i = increment(i) }; return cond(i) }()) {
}

Interestingly, this behaves correctly with both continue, break, and throw. It's not pretty, but this struct will make a little bit easier on the eye:

/// Provide a suitable condition for recreating the control flow of a C-style `for`
/// loop within a `while` loop.
///
/// var loop = CForLoop()
/// var i = 0
/// while loop.test(i < 2, {i += 1}) { ... }
///
/// - Note: You have to make a new controller each time you start a loop.
struct CForLoop {

  /// Flag to prevent the increment part from executing on the first iteration of
  /// the loop.
  private var first = true

  /// If this is the first call of test, simply evaluate `predicate` and return
  /// its value. Subsequent calls will execute `increment` before evaluating
  /// `predicate`.
  /// - Parameter predicate: The test condition that must be true for the loop to
  /// continue. This is the second statement in a C-style `for` loop.
  /// - Parameter increment: The code to execute just before re-evaluating the
  /// predicate at the end of one loop iteration. This is the third statement
  /// of a C-style `for` loop.
  /// - Returns: The value returned by predicate. This value should be used as
  /// the condition in a `while` loop.
  mutating func test(@autoclosure predicate: () -> Bool, _ increment: () -> ()) -> Bool {
    if first {
      first = false
    } else {
      increment()
    }
    return predicate()
  }
}

···

Le 7 déc. 2015 à 21:03, Joe Groff <jgroff@apple.com> a écrit :

A more accurate (but not particularly pretty) substitution would be to perform the increment as part of the condition:

while { i = increment(i); return cond(i) }() {
}

--
Michel Fortin
michel.fortin@michelf.ca
https://michelf.ca