Swift and mutating struct

后端 未结 8 1690
鱼传尺愫
鱼传尺愫 2020-12-04 06:54

There is something that I don\'t entirely understand when it comes to mutating value types in Swift.

As the \"The Swift Programming Language\" iBook states:

相关标签:
8条回答
  • 2020-12-04 07:34

    I wondered the same thing when I started learning Swift, and each of these answers, while adding some insights perhaps, are kind of wordy and confusing in their own right. I think the answer to your question is actually pretty simple…

    The mutating method defined inside your struct wants permission to modify each and every instance of itself that will ever be created in the future. What if one of those instances gets assigned to an immutable constant with let? Uh oh. To protect you from yourself (and to let the editor and compiler know what you're trying to do), you're forced to be explicit when you want to give an instance method this sort of power.

    By contrast, the setting of a property from outside your struct is operating on a known instance of that struct. If it's assigned to a constant, Xcode will let you know about it the moment you've typed in the method call.

    This is one of the things I'm loving about Swift as I start to use it more—being alerted to errors as I type them. Sure beats the heck out of troubleshooting obscure JavaScript bugs!

    0 讨论(0)
  • 2020-12-04 07:41

    The mutability attribute is marked on a storage (constant or variable), not a type. You can think struct has two modes: mutable and immutable. If you assign a struct value to an immutable storage (we call it let or constant in Swift) the value becomes immutable mode, and you cannot change any state in the value. (including calling any mutating method)

    If the value is assigned to a mutable storage (we call it var or variable in Swift), you're free to modify the state of them, and calling of mutating method is allowed.

    In addition, classes don't have this immutable/mutable mode. IMO, this is because classes are usually used to represent reference-able entity. And reference-able entity is usually mutable because it's very hard to make and manage reference graphs of entities in immutable manner with proper performance. They may add this feature later, but not now at least.

    For Objective-C programmers, mutable/immutable concepts are very familiar. In Objective-C we had two separated classes for each concept, but in Swift, you can do this with one struct. Half work.

    For C/C++ programmers, this is also very familiar concept. This is exactly what const keyword do in C/C++.

    Also, immutable value can be very nicely optimised. In theory, Swift compiler (or LLVM) can perform copy-elision on values passed by let, just like in C++. If you use immutable struct wisely, it will outperform refcounted classes.

    Update

    As @Joseph claimed this doesn't provide why, I am adding a little more.

    Structs have two kind of methods. plain and mutating methods. Plain method implies immutable (or non-mutating). This separation exists only to support immutable semantics. An object in immutable mode shouldn't change its state at all.

    Then, immutable methods must guarantee this semantic immutability. Which means it shouldn't change any internal value. So compiler disallows any state changes of itself in a immutable method. In contrast, mutating methods are free to modify states.

    And then, you may have a question of why immutable is the default? That's because it's very hard to predict the future state of mutating values, and that usually becomes the main source of headaches and bugs. Many people agreed that the solution is avoiding mutable stuffs, and then immutable by default was on top of wish list for decades in C/C++ family languages and its derivations.

    See purely functional style for more details. Anyway, we still need mutable stuffs because immutable stuffs have some weaknesses, and discussing about them seems to be out of topic.

    I hope this helps.

    0 讨论(0)
提交回复
热议问题