Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

While with assignment in swift

Tags:

swift

What is the proper way to convert this Objective-C code into Swift?

while ((size = [inputdata readWithByteArray:buf]) != -1) {
  //...
}

I need similar to this (from here):

while let super = view?.superview {
  count++
  view = super
}

but in my case i have to compare the value with -1 instead of nil.

like image 782
Vyacheslav Avatar asked Sep 30 '16 13:09

Vyacheslav


Video Answer


2 Answers

You can use while case with a binding pattern plus a boolean condition:

// Swift 3 (Xcode 8):
while case let size = inputdata.readWithByteArray(&buf), size != -1 {
    // process data

}

// Swift 2 (Xcode 7.3.1):
while case let size = inputdata.readWithByteArray(&buf) where size != -1 {
    // process data

}

(Previous answers:) A straight-forward implementation would look like this:

var size = inputdata.readWithByteArray(&buf)
while size != -1 {
    // process data ...

    size = inputdata.readWithByteArray(&buf)
}

If the code-duplication bothers you then you can write it also as (Swift 3/Xcode 8 only):

var size: Int
while (size = inputdata.readWithByteArray(&buf), size).1 != -1 {
    // process data

}

Here the (...).1 expression evaluates to the second tuple element, i.e. to size, and the first tuple element is only evaluated for its side-effect. (This is possible in Swift because expressions are evaluated from left to right, as stated by Chris Lattner in https://forums.developer.apple.com/thread/20001#63783.)

like image 140
Martin R Avatar answered Nov 15 '22 09:11

Martin R


I found the tuple-based code from the accepted answer quite interesting for solving the issue posted in the question.

Here the if (..., boolean).1 { expression evaluates the second tuple element, a boolean, and the first tuple element is only evaluated for its side-effect.

So you can do things like inline the index decrement in the while loop condition, rather than on a line before or after:

var index = 5
while (index -= 1, index >= 0).1 {
    print(index)
}

// 4
// 3
// 2
// 1
// 0

Whereas the while case let construct does not allow the previous assignments to index to persist in the next iteration of the loop:

var index = 0
while case let index = index + 1 {
    print(index)
}

// 1
// 1
// 1
// 1
// infinite loop
like image 24
pkamb Avatar answered Nov 15 '22 09:11

pkamb