Wednesday, November 4, 2015

Swift 2.0, Reference and Value Types, and Unintended Sharing.

I have recently begun learning swift 2.0, because I would like to build an iOS app and I really don't want to have to learn Objective-C.  I am trying to learn it the right way, which means understanding how the language works and not just mutating examples to learn by accident.

I have been reading a lot about structs and classes, and the difference between value types and reference types.  In short, classes pass around object references and structs make copies whenever you pass them around.  I visualize it in old-school terms:  Classes use pointers, but with structs the variable IS the data.

This seems pretty simple - especially if you are comfortable with object languages.  I have watched a few Apple videos, though, and they make it sound revolutionary.  This one in particular goes on about unintended sharing - I pass a handle to the same object into two different contexts where they are expected to be independent.  Change one, impact the other, etc.  His illustrative example was "I created a thermostat object, assigned it to my house.  Then I set the thermostat in my oven to 450, and my house caught on fire!"  Paraphrase.  Gag - what a juvenile way to introduce a language feature.  They could have at least used a real-world scenario they came across implementing their standard libraries that made this feature such a deal-maker.

This seems to me to be very valuable to a college student, or someone learning an object language coming from C, but really, is this that big of a deal?  I can honestly say that I haven't had a bug of this type in my code, that I have detected of course - for decades.  On the other hand, I just spent an agonizing couple of days trying to figure out why extremely routine code did not work.  Take this example:

var map = [String: [String: String]]();
var subMap = [String: String]();
map["map"] = subMap;

subMap["1"] = "2";

For those who don't know swift, this means create a map which can hold maps of string value/pairs.  Next, create a string value/pair map, and assign it to the key "map" in the top-level map.  Finally, assign the key/value entry "1" -> "2" into the sub map.  The expectation being that it will be reflected in the top-level map as well.  This is pretty standard in Java - I do it a lot so I can factor code which handles the sub trees into external code.  In this case, it doesn't work.  Because collections in swift are structs - I.E., value types - the assignment on the third line makes a copy which is unaffected by the assignment on line 4.  I came up with this working code after much hair-pulling:

var map: Dictionary = [String: [String: String]]();
map["map"]!["1"] = "2";

And only later uncovered the reason that I explained before.  I find this extremely annoying, but certainly manageable once you understand the language - and maybe even something you can use effectively.  But I found his example so contrived that I basically checked out.

No comments:

Post a Comment