1

I came across such statements as the following in Matt Neuburg's iOS 13 Programming Fundamentals with Swift:

When you cycle through a sequence with for...in, what you’re actually cycling through is a copy of the sequence. That means it’s safe to mutate the sequence while you’re cycling through it:

And the author supplied the following example for the above statements:

var s : Set = [1,2,3,4,5]
for i in s {
    if i.isMultiple(of:2) {
        s.remove(i)
    }
} // s is now [1,3,5]

In the example above, we can see that the original array was altered from [1,2,3,4,5,6] to [1,3,5]. That means the array itself was changed. So, the for in loop wasn't looping through a copy of the original array but the array itself. That seems to contradict the author's statements above.

So, I'm not sure whether the author's statements are true or not. Would anyone please clarify this matter? Thank you very much.

3
  • 6
    If it wasn't looping through a copy as soon as you started removing elements whole loop would go wrong and crash the app. You can check what would happen in Objective C for example. Commented Jul 6, 2020 at 8:30
  • 2
    Of course does s.remove(i) remove the element from the set s... Commented Jul 6, 2020 at 8:34
  • 3
    Related: Remove element from collection during iteration with forEach. Commented Jul 6, 2020 at 8:37

3 Answers 3

6

The wording might be a bit misleading at first sight, but the statement that for i in s loops through a copy of the original s is true. If it wasn't true, you'd get an out of bounds exception or an unexpected result (some elements of the collection being skipped), since you would be mutating a collection while you are iterating through it.

When you create the loop with for i in s, a copy of s is created and the iteration happens through that copy. However, when you access s inside the body of the loop, you are accessing the original s and hence mutating that, not mutating the copy that the loop is iterating through.

Sign up to request clarification or add additional context in comments.

Comments

4

There a little of a nuance here. The array that you iterating over is a copy, but the array that you are modifying is still the original.

In other cases, this code would end up skipping a few elements due to the index changes.

If this was not the case, then consider the following iterations

// i = 0
// s = [1,2,3,4,5]
// evaluation 1.isMultiple(of: 2)
// element to be removed: none
// i = 1
// s = [1,2,3,4,5]
// evaluation 2.isMultiple(of: 2)
// element to be removed: 2
// Here is where the problems would start, since the number 3 would be skipped.
// i = 2
// s = [1,3,4,5]
// evaluation 4.isMultiple(of: 2)
// element to be removed: 2

Since you are iterating over a copy, you can modify s and still make sure that all the elements will be considered.

Comments

-1

Actually, in a way, you answered your own question when you wrote,

That means the array itself was changed.

This is true because you ended up with // s is now [1,3,5] after your for in loop finishes iterating through the sequence. The problem is with the sentence after.

So, the for in loop wasn't looping through a copy of the original array but the array itself.

Your first sentence directly implies that the for in loop was looping through a copy of the original array and not the opposite.

5 Comments

(I noticed your meta question about being autofiltered, so I thought I might comment on some example post of yours to make a suggestion for your future consideration.) An answer such as this does not add information beyond what already appears in the accepted answer. It makes an observation about the question and OP's assumptions. It would have probably made better sense as a comment. Moreover, seeing how it is made four years after the fact - it is not even very useful as a comment at this point /...
.../ When posting questions or answers, try to think about their benefit to people who are not yourself nor a person you are replying to: Should they care about what you're writing? Is it important for them to know/understand? In the case of this answer - not really.
I’ll keep this in mind going forward, thank you. :)
Another point is when you're pointing out an error or misconception in the question, it's often better to avoid using the second person, so as not to sound accusative/derogatory (even if it's in a comment rather than an answer), or to replace phrases such as "you have done X" or "you wanted to do Y" with "I believe you may have done X" and "assuming you wanted to do Y" - so as to let the other person be the one acknowledging what they've done.
I appreciate your remark, but I disagree. I don’t think the tone here was derogatory or accusatory by addressing the person directly. Thanks again.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.