 ThinCL
|
ThinCL (rhymes with
'tinkle') is short for this not
CLOS. The philosophy of ThinCL is to
give a type secure class extension to Qi that is
open coded,
easily modified because coded in a small space
provides about 90% of what people would generally want
easy to learn
type secure
a platform for multiple inheritance and defaults
uses lists as the basic constructor for classes and
instances
avoids destructive operations as far as possible
efficient
CLOS did not satisfy all these
requirements and hence ThinCL. ThinCL is 187 lines of Qi
source.
The basic operations are
1. class creation
2. class instantiation
3. grabbing the value of an attribute in an instance
4. seeing if an attribute has a value in an instance
Class Creation
(defclass ship [ ]
name string;
tonnage number;
speed number;
crew number;)
assigns 'ship' to the type class. The
list (here empty) following the identifier gives the
superclasses. The pairs before each semi-colon give the
name of the attribute and the type of its value. Triples
are also acceptable
(defclass destroyer [ship]
torpedoes number 22;
guns number 2;)
This class takes ships as a superclass
and adds new attributes whose default values are 22 and
2.
(make-instance ship) creates an
instance of a ship. get-value takes an instance
and an attribute and returns the value of the instance in
that attribute. has-value? takes an instance and
an attribute and returns either true or false depending
on whether a value exists or not. change-value changes the value
of an attribute in an instance. super takes a list of classes
and returns the list of all superclasses. These are all
type secure.
Examples:
(4+) (defclass ship
[ ]
name string;
tonnage number;
speed number;
crew number;)
ship : class
(5+) (defclass destroyer [ship]
torpedoes number 22;
guns number 2;)
destroyer : class
(6+) (make-instance destroyer)
[[name . fail!] [tonnage . fail!] [speed . fail!] [crew .
fail!] [torpedoes . 22] [guns . 2]] : (instance
destroyer)
(7+) (make-instance destroyer) : (instance ship)
[[name . fail!] [tonnage . fail!] [speed . fail!] [crew .
fail!] [torpedoes . 22] [guns . 2]] : (instance ship)
(8+) (let D
(make-instance destroyer)
(do (output "~A~%" (has-value? name D))
(output "~A~%" (has-value? guns D))
(output "~A~%" (get-value guns D))
(output "~A~%" (has-attribute? size D))
(change-value D tonnage 1000)))
false
true
2
false
[[name . fail!] [tonnage . 1000] [speed . fail!] [crew .
fail!] [torpedoes . 22] [guns . 2]] : (instance
destroyer)
(9+) (defclass
cruiser [ship]
name symbol;)
name should have type string, not symbol
type error
Type Theory
make-instance :
(class Class) --> (instance Class)
get-value : (attribute Class A) --> (instance Class)
--> A
has-value? : (attribute Class A) --> (instance Class)
--> boolean
has-attribute? : symbol --> (instance Class) -->
boolean
instance-of : (instance Class) --> (class Class)
change-value : (instance Class) --> (attribute Class
A) --> A --> (instance Class)
super : (list class) --> (list class)
defclass is a
sugared function; the non-sugared syntax is implicit in
the following type theory.
(datatype
classdeftype
Id : symbol;
SuperClasses : [class]; ClassDef : [slot];
(defclass Id SuperClasses ClassDef) : class;
C : (class A);
==============
C : class;)
(datatype
slotdeftype
\ Type consistency test - subtypes follow subclasses; \
Attribute : (attribute Class B);
(notsubtype A B);
!; (attribute-clash-error Attribute A B);
_________________________
[Attribute A | _] : slot;
Attribute : symbol;
===================
[Attribute A] : slot;
Attribute : symbol;
Default : A;
============================
[Attribute A Default] : slot;
let Message (output "~A should have type ~A, not
~A~%" Attribute B A)
if false
_____________________________________
(attribute-clash-error Attribute A B);)
(datatype notsubtypetest
let X (gensym "&&")
X : A >> X : B; !; fail;
(notsubtype A B);
_______________
(notsubtype A B);)
Defaults must of course inhabit the appropriate types
and Qi checks this. Also an attribute A may be given a
type T in a class C even if A is given a type T* in a
superclass of C provided T is a subtype of T* i.e. X : T
>> X : T* is provable for an arbitrary X. To
remember this just remember the motto:
subtypes follow subclasses.
Mark
Copyright (c) 2009, Mark
Tarver
dr.mtarver@ukonline.co.uk
|