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.
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.