Next: 3.15 Modules
Up: 3 The Slate World
Previous: 3.13 Concurrency
Contents
Index
Subsections
3.14 Types
In coordination with the reserved
syntax for type-annotation in block headers, the standard libraries
include a collection of representations of primitive TYPES
as well as quantifications over those types. The library of types
is laid out within the non-delegated namespace Types in the
lobby.
- Any
- The type that any object satisfies:
the universal type.
- None
- The type that no object satisfies:
the empty type.
- Range
- A
parametrized type over another type with a linear ordering, such as
Integer. This type is bounded, it has a start and
a finish (least and greatest possible member). In general,
any Magnitude can be used as a base of a Range type.
- Member
- The type associated with membership
in a specific set of objects.
- Singleton
- The type of a single
object, as distinct from any other object.
- Clone
- The type of an object and its
CLONE FAMILY, the set of objects that are direct copies (clones
plus changes to slot values) of it.
- Array
- The type representing all arrays,
as parametrized by an element type and a length.
- Block
- The type representing code closures
of a given (optional) input and output signature.
Types
may be combined in various ways, including union:, intersection:,
and extended via derive which preserve type constraints on
the derivations.
Local slot specifiers
in a Method header as well as input slot specifiers may have types
optionally declared within the header. Within a method declaration
expression, the input slots may be redundantly specified in the header
as well as in the dispatch expression. However, if this is done, the
header's specifier needs to be specified as an input slot and if multiple
input slot types are specified, they should be specified in order.
The
syntax is similar to that for @-based dispatch notation:
follow the slot name with the bang character ``!'' and
then a type expression, which may be a primitive or derived type.
For example,
-
- [| :foo!Integer bar | bar: (foo raisedTo: 3).
foo + bar] applyWith: 4.3.
Type annotations don't use primitive expressions: the evaluator doesn't
have a library of pre-built types at its disposal. Instead, Type annotation
expressions are evaluated within the namespace named Types
accessible from the lobby. For this reason, user-defined
named types should be installed in some place accessible through the
Types path.
Type-inference
on syntax trees is driven by calling inferTypes on the Syntax Node
in question. This will process type information already annotated
to produce derived annotations on related nodes.
Also, there is a facility to extend the type-inference
capability per method. To explain, each Type object comes with a rules
object slot that is dual to the traits delegate object; rules delegate
as the traits do but do not confer to the types their methods. Instead,
they are used by the inference system transparently to allow for more
intelligent specialization. To wit:
-
- _@((Member of: {True. False}) rules) ifTrue: then@(Block rules)
ifFalse: else@(Block rules)
[
then returnType union: else returnType
].
is a type-inference extension method for #ifTrue:ifFalse:
for any boolean and a pair of blocks, that the return type will be
in the union of the blocks' return types.
Next: 3.15 Modules
Up: 3 The Slate World
Previous: 3.13 Concurrency
Contents
Index
Brian Rice
2005-11-21