I'm just looking for what it is that sets Self apart from Smalltalk.
This isn't supposed to be a Gorilla vs Shark question. I'm not looking for reasons one is better, I'm just confused as to what defines one as being distinct from the other. They both appear to be the same language to me after about 2 hours of reading up on them and mucking around with some code (Aside: I finally understand the Smalltalk version of "Everything is an object". I must say, it's bloody awesome. Haha! And I thought that C# had it nailed... but it doesn't even come close to this! XD)
Random things that I've read somewhere, some time over the past few years:
The most distinct difference between Self and Smalltalk is that Self does not have the notion of Classes. There is no “is an instance of” relation between an object and a class. Self rather has been one of the first prototypical object-oriented language, and in this respect a precursor to JavaScript. Hence, the typical way to create a new object in Smalltalk is instantiation whereas in Self it is cloning.
As you already have found out, the second fundamental difference is that in Self, the only notion of execution is the message send, whereas in Smalltalk, assignment and object field access also are present. Furthermore, there is no such thing as global state in Self. You can only access what you can retrieve by sending messages. Self however tracks some “well known objects”, which a newly created object can be given.
Pondering on the two previous points, “No classes” and “only messages”, makes it clear, that the Smalltalk distinction between and objects state and its behavior is not directly present in Self. Where Smalltalk stores state in an objects’s instances variables and behavior in method dictionaries in its class, Self uses the notion of slots, which can represent both state and behavior.
To help organizing behavior, Self not only provides prototypes but also traits. A trait is an object that only contains behavior, and which several objects share. (Moreover, there are also mixins, small portions of behavior and state, that can be composed into other objects).
Objects in Self can have parents to which messages are sent that the object itself does not understand (delegation). This creates hierarchies that can be similar to class inheritance in Smalltalk, but does not need classes.
Object new
Self:
()
or (||)
(to make the absence of slots explicit)someObject copy
Object subclass: #MyObjects instanceVariableNames: 'foo bar'. "…"
MyObject new.
Self
( | foo. bar | )
OrderedCollection new.
Self
list copy.
Object subclass: #MyObject. "…"
Self
( | parent* <- list | )
I suggest reading the bibliography section on the Self webpage.