Should I use a Swift struct or a class?
faq.sealedabstract.com
faq.sealedabstract.com
Use structs when you want value semantics. Use classes when you want reference semantics. Boom. Done.
All the confusion and discussion and fighting seems to be because people don't understand the implications of value versus reference semantics, and instead of learning they try to come up with ad hoc rules and guidelines that will let them decide without understanding the actual differences.
I think you've correctly identified the source of confusion -- value vs reference. To you, that might be plain as day. But, to many iOS devs, they really couldn't explain the nuances.
I mean, look how much trouble beginner programmers have with the concept of Pointers for pete's sake.
But, I think you're right -- weird rules and guidelines just confuse the issue.
Andy Matuschak's functional swift talk puts the ref vs value discussion in practical terms of a Khan Academy drawing app:
I've never written a line of Obj-C or Swift in my life, but all you have to tell me is "struct = value based, class = referenced based" and I immediately know how it works...
It has to do with learning stuff on a lower level -- whether or not you attend a school to do so. Us autodidacts who grew up on assembly language and C code will beg to differ on your use of the word "prevents".
Do you have any books or exercises to recommend to help further my understanding of low-level computing? I'll be taking too and compilers in the fall, but I'd like to keep digging on my own.
It worries me, to a degree, because there's probably no way to make a programming language smart enough to protect users from these people.
But wow, this post... I've no idea how he came to the conclusion structs=functional. He just sorta dives into it? If you aren't sure on something, why not read up a bit more? Guess C is a really functional language since it's got structs everywhere.
That's simply due to a lack of analysis. In many cases it's easy to show the object is short lived. Yet there's no way to annotate this and AFAIK, the JIT doesn't even try to figure this out.
var x = 42
var y = x
x++
print x // 43
print y // 42
It seems that, for whatever reason, people understand this but have a really hard time generalizing it. It's not even a matter of custom types being a confounding factor, as I've seen deep confusion over the fact that Swift collections have value semantics.A) One must ensure that one's callers are also mutating, or otherwise have an assignable reference, all the way up the stack
B) One must mark the applicable function in the protocol interface as mutating, which may or may not be under your control
C) One must now repeat step A for all consumers of the protocol in step B, even if none of the other implementations of that protocol mutate their own state
Of course one can design one's architecture specifically with a view toward making ABC trivial, but in the general, unrestricted, default, I-had-other-problems-that-day-and-didn't-think-about-it case, they are hard.
That is why I find calls to "just learn value semantics" necessary but insufficient. Value semantics will not refactor my code when I discover-by-surprise that 18 functions need to become mutating, breaking API compatibility across several build targets, because I failed to forsee a necessary mutation 8 months ago.
let a = MyStruct(x: 1, y: 2)
let b = a // Creates a copy of `a`
b.x = 3 // Won't compile because you used "let", so its properties are immutable
var c = a
c.x = 3
println(a.x) // Prints "1"; the original instance doesn't get changed
let d = MyClass(x: 1, y: 2)
let e = d // Refers to the same object as `d`
e.x = 3 // Allowed, even though you used "let"
println(d.x) // Prints "3"
That's a basic illustration of the difference between value types and reference types, but there are other differences between structs and classes as well (for instance, structs don't support inheritance or deinitializers).Without referential equality things like mutation fail to have any sense, but programs are in general simpler.
State changes are fine! They just aren't allowed to be hidden.
Despite all that - I agree that move semantics are weird. He's got a point there.
1) Make it not mutable 2) Make it not shared
But these are still "state", so I'm not really sure what the hell the article is on about.
Guaranteed to work.
The author is correct about when to use both, and I'm glad he doesn't discount structs entirely like I've seen from some OOP strongholds.
"The way they write functional programs for decidedly non-functional problems is through a trick called a monad, which I will not explain and nobody understands anyway,"
Maybe you'd be less hostile if you actually took the time to learn about generic abstractions and how they can greatly simplify a codebase.
Hint: Optional is a monad, and you can use it as such.
You should not use an embedded class in a struct if it is not a singleton, as in the UIBezierPath example, where when you copy the struct, you expect to do a copy-on-write of the class to avoid mutating all copies in all structs
Nice. What can possibly go wrong?
Looking forward to seeing the questions in the swift SO site.