NOTE: http://www.quag.geek.nz/io/setSlot-updateSlot has a newer html version of this document. I think of := and = removing ambiguity between locals and slots on self. With a single assignment operator doing double duty for updating and initialising slots it is impossible to tell if a variable is a local or on self by only looking at a method. Consider the following method: f = method(a, x = a + 2 writeln(x * 3) ) Clearly x is a local. Right? Maybe not. Lets see what happens when f is shown in context. o = Object clone do( x = 0 f = method(a, x = a + 2 writeln(x * 3) ) g = method(b, writeln(x * b) ) ) Now it appears that x is a slot on the object o. The code for the two f methods is identical yet in one it x appears to be a local variable, and in the other x appears to be a slot on self. To work out if a variable is a local or on the object you have to read all of the code for the object. Having to read all of the code on the whole object doesn't sound so bad does it, so let me be really evil. o = Object clone do( f = method(a, x = a + 2 writeln(x * 3) ) ) o f(1) # prints 9 # Time to add some more functionality... o g = method(b, writeln(x * b) ) o x := 13 # Lets test o g to make sure it works. o g(3) # prints 39 # Looks good. :) Live is good. Time to use our working object... o f(1) # prints 9 o g(3) # prints 9 wait a minute... that printed 39 a minute ago... # yes... so it was. But how was I to know that o f had a local variable called # x?! What happens if a proto adds a slot which also happens to be the name of # a local variable?! All hell breaks loose, that's what happens. and so on... The key step for me was proving to myself that := and = could not be unified because it would be ambiguous if a variable was local or not. (You said this the other way around. I find it helpful to think of it as identifying locals, rather than identify slots on self because it is the locals which cause the trouble.) There are two types of solutions. 1. Explicitly access slots on self. Typically via prefixing member slots with a "self" or "this" keyword or some kind of character like "@" or "$". - self and this are a bunch of extra typing - @ and $ look ugly and are a pain to type 2. Explicitly marking initialisation/declaration of variables. This lets you know when a variable is being created locally instead of updating an existing slot on self. a) C/C++, Java and so on already require variable declarations for type information so they use those declarations to indicate if a variable is local or not. b) Use a "local" or "var" keyword to prefix local variable declaration. (It is only the local declarations we care about after all.) - Javascript does this - almost all variables end up being prefixed with "var" except for global variables... which is the wrong way around... it is globals which are rare and should require extra typing and warning... So people often leave the "var" off and make everything a global when they are being lazy. In Io's case, people would be lazy and make all local variables slots on self-equally bad. c) Make all initialisation explicit. (:= and =, or a "var" keyword which is always required). - What Io uses. - Causes confusion because people don't understand why := and = are needed. - Picking a universal var keyword would have been easier for people to accept.