[swift-evolution] C-style For Loops

Kevin Lundberg kevin at klundberg.com
Sun Dec 6 20:45:13 CST 2015


> As it was pointed out earlier, converting to a while loop requires duplication of the "increment" part of the loop everywhere there is a `continue` inside the loop.
This is not necessarily true. `defer` could be used at the top of the
while loop scope to increment whenever the loop turns. The after-fixit
example you gave can be written like so:

do {
	var i = 10
	while i >= 0 {
		defer { i -= 1 }
		if i == 5 {
			continue
		}
		do {
			var j = 100;
			while j >= 0 {
				print("\(i) \(j)")
				j -= 2
			}
 		}
	}
}



On 12/6/2015 9:10 PM, Michel Fortin via swift-evolution wrote:
> Le 6 déc. 2015 à 16:08, ilya <ilya.nikokoshev at gmail.com> a écrit :
>
>> There are a couple of ways of solving this issue:
>>
>> 1 refactor to where loop first, then convert to Swift 
> This assumes 1) that you have a working toolchain to compile, execute, and test the original code, and 2) that the other language has a way to express the loop in a similar way to Swift, or something close enough.
>
>
>> 2 leave a fixit in Xcode that will perform while loop conversion 
> As it was pointed out earlier, converting to a while loop requires duplication of the "increment" part of the loop everywhere there is a `continue` inside the loop. While you could make a fixit that correctly does this, I would argue that duplicating code shouldn't be done so lightly (someone will have to edit or maintain it afterwards). It's unclear to me what else could be done here however, as I can't think of a refactoring that would prevent code duplication. (And defer shouldn't be used here because it has a different behaviour when an exception is thrown.)
>
> The fixit probably should also introduce a do{} block to correctly scope the loop variable and avoid clashes with the surrounding context.
>
> It remains that even with a fixit that changes the code like this, the various differences it'll create in line count, increment expression placement, indentation, and sometime duplicated code, are going to impair your ability to compare the two loops side by side when hunting for porting bugs. Also the Swift version, the one that compiles thanks to a fixit, will simply be less readable... to the point that it'll generally be better to just do the refactoring as you port, despite the downsides.
>
> Before fixit:
>
> 	for var i = 10; i >= 0; i -= 1 {
> 		if i == 5 {
> 			continue
> 		}
> 		for var j = 100; i >= 0; j -= 2 {
> 			print("\(i) \(j)")
> 		}
> 	}
>
> After fixit:
>
> 	do {
> 		var i = 10
> 		while i >= 0 {
> 			if i == 5 {
> 				i -= 1
> 				continue
> 			}
> 			do {
> 				var j = 100;
> 				while j >= 0 {
> 					print("\(i) \(j)")
> 					j -= 2
> 				}
> 			}
> 			i -= 1
> 		}
> 	}
>
>



More information about the swift-evolution mailing list