Prototype-based Objects

Slate descends from the Self programming language, where object-centered development is emphasized. So, instead of instantiating classes to form new objects, pre-existing objects are copied or cloned and modified to produce new ones. Re-use of existing code, data, and behavior is accomplished through delegation between objects: whenever a service is requested of an object which is not defined directly by it, it consults the objects in slots marked for delegation for the same services with the original object as the argument.

Slate, however, takes after Smalltalk in that the syntax distinguishes between objects and block closures (or methods) syntactically. The literal object syntax of Self does not carry forward into Slate.

Objects and Slots, and Delegation

Slate provides several primitive messages to manage slots:

object addSlot: slotSymbol
Adds a slot using the symbol as its name, initialized to Nil.
object addSlot: name valued: val
Adds a slot under the given name and initializes its value to the given one.
object addDelegate: slotSymbol and object addDelegate: slotSymbol valued: val
Adds a delegation slot, and initializes it, respectively. It is usually preferred to use the latter since delegation to Nil is unsafe.

Each of the former has a variant which doesn't result in a mutator method being generated for its slot: addImmutableSlot:valued: and addImmutableDelegate:valued:.

The Primitive Object Hierarchy

Root
The "root" object, upon which all the very basic methods of slot manipulation are defined.
Oddball
The branch of Root representing non-cloneable objects.
Nil
Nil is an Oddball representing "no-object".
Derivable
Derivable objects respond to derive and deriveWith:, which means they can be readily extended.
Cloneable
Cloneable objects are derivables that can be cloned.
Method
A Cloneable object with attributes for supporting execution of blocks and holding compiled code and its attributes.

Blocks

Blocks in Slate are procedures with input and local argument possibilities that are packaged as separate objects. Blocks are not executed when they are defined; they must be sent messages to be evaluated, and can be re-evaluated later on. When a block is evaluated, a special activation object is created which holds its execution state, and is then discarded after being used.

Blocks also have the property of lexical closure: that is, they "remember" the environment in which they were defined, but can also be returned as values and invoked elsewhere, still recalling implicitly what was present where they were defined.

Methods

Methods are procedures that are associated with a number of objects. They have arguments which are their inputs, and dispatchers which are "co-owners" of the method. Arguments in Slate are always named, and occur in a position within the call to a method called a message. The name of a method is called its selector, and in Slate often consists of a number of keyword-style words joined together.

When a method is defined, it must be dispatched to one or more objects for some argument positions. These objects are found and annotated with the method is defined. These annotations are what defines the method's applicability: the system ensures that objects given for argument positions that are dispatched must inherit from those objects.

Because of the importance of roles and annotations in Slate method definitions, method objects are not the sole property of a given dispatch object. Methods stand alone as code blocks.

Messages and Dispatch

A message in Slate is a polymorphic procedure call. When a message is sent to a number of objects, the system determines dynamically (by default) what method is invoked in response. The method will have the same name as the message's selector, and will be found by looking into the objects and their inheritances for dispatch associations that match. In Slate, all arguments are consulted to determine what method is called; this is referred to as multiple dispatch in contrast to single dispatch for most common object-oriented languages.

Objects and Roles

When methods are defined, the annotation made from a dispatched object to the method is called a role: this emphasizes that the object is a representative of those objects which can play a role in that method by being present in that argument position. So a role annotation says: "I and those inheriting from me may show up in this method with that name in that position". Any object may have role annotations, and the roles can be for any position.

Co-operative Lookup

The process of determining the appropriate method to invoke for a message-send is the lookup process. This is performed by consulting all of the arguments themselves and the objects that they inherit. A few basic factors are involved in determining the appropriateness of the methods found: