In SPAD:
- '%' is used to represent a domain
- 'Rep' is its underlying representation
Casts between these are usually implicit but sometimes we need functions/macroes to convert between them:
- rep(x:%):Rep == x pretend Rep
- per(x:Rep):% == x pretend %
Lisp Implementation
It seems hard to undersand how to create data structures (especially 'Rep') until we realise that, when we are working in SPAD, The language Lisp is just below the surface.
Therefore the best way to study data structures is to look at the lisp output, I have therefore created a very simple domain which allows me to see the lisp structure each data type creates:
)abbrev domain TEST TestRep TestRep(): T==C where T== with test:() -> % C== add Rep := Record(v: NonNegativeInteger) test(): % == [5] |
When we create an instance of Rep, we get,
(1) -> test() LISP output: (5) Type: TestRep |
I therefore used this program, modifying 'Rep' and the constructor with every type of data that I could think of. I then put the results in this table.
type | SPAD | Lisp Output |
---|---|---|
integer | Rep := NonNegativeInteger test(): % == 5::NonNegativeInteger |
5 |
float | Rep := Float test(): % == 0.5 |
(147573952589676412928 . -68) |
boolean | Rep := Boolean test(): % == true |
T |
character | Rep := Character test(): % == char("a") |
97 |
string | Rep := String test(): % == "a string" |
a string |
list | Rep := List NonNegativeInteger test(): % == [1,2,3] |
(1 2 3) |
list (empty) |
Rep := List NonNegativeInteger test(): % == [] |
NIL |
record | Rep := Record(v: NonNegativeInteger)
test(): % == [5] |
(5) |
union (part 1) |
Rep := Union(NonNegativeInteger,String) test(): % == 5::NonNegativeInteger |
(0 . 5) |
union (part 2) |
Rep := Union(NonNegativeInteger,String) test(): % == string(123) |
(1 . 123) |
type | Rep := Type test(): % == NonNegativeInteger |
>> System error: The value |NonNegativeInteger| is not of type LIST. |
quaternion | Rep := Quaternion(Float) test(): % == quatern(0.1,0.2,0.3,0.4) |
UNPRINTABLE |
symbol | Rep := Symbol test(): % == a |
a |
equation | Rep := Equation(Polynomial(Integer)) test(): % == equation(a%,3) |
>> Apparent user error: cannot compile (equation %a 3) |
variable | Rep := Variable(a%) test(): % == a% |
References
In addition to direct data we also want to have pointers or references, this allows us to create linked lists, trees and similar structures. So how do we put a pointer into Rep? One way seems to be to use List % which seems to be interpreted as a pointer (using Rep := % on its own seems to cause an error):
)abbrev domain TEST TestRep TestRep(): T==C where T== with test:(next:%) -> % C== add Rep := List % test(next:%): % == next |
So first in (1) we construct an instance with an empty list, then in (2) we construct an instance with a pointer to (1),
(1) -> t1 := test([]) (1) test Type: Symbol (2) -> t2 := test([t1]) (2) test test Type: Symbol |
So that allows us to point to an instance of the same type but how do we point to instances of other types?
type | SPAD | Lisp Output |
---|---|---|
pointer to another instance of same type. | Rep := List %
test(next:%): % == next |
test |
Types
how are types represented as variables? That is we want a variable say:
myType: Type
which might be set to NonNegativeInteger, Float, String and so on.