]> ocean-lang.org Git - ocean-D/blob - I Object
updates
[ocean-D] / I Object
1 NOTE - where to put stuff about "is natural a type, is non-zero a type (for div)"
2
3 Objects and polymorphism, and some standard chalenges
4
5 Some definitions:
6
7 Object       a record of operations
8
9 Operation    a function specific to, and depending on, and part of, an obect
10
11 Expectation  what an operation (in high level, abstract, programmer based sense) expects of 
12              its operands
13
14 Behaviour    a specification of what an object ('s operations) does
15
16 '' vs State  behaviour can be modeled as procedure plus state
17
18 Types        subset of behaviour that satisfies expectation
19              also a set of object which share this subset of a behaviour
20
21              sum of types of operations
22
23 Subtypes     relation between behaviours
24              co variance/ contra-variance
25
26
27 Polymorphism two objects in the same type conform to same expectation and so can
28              equally be arguments to an operation
29
30 Examples....
31
32
33 Behaviours(?) that don't fit the model  
34                 stack
35                 total ordering
36
37 Parameterised behaviours
38                 stack of plates
39                 ordering of numbers
40
41 Class:          this that creates object - the set of those object - hence like a type
42
43 Other Issues
44         infix (mult, add)
45                 declared in parent (field)
46                 refined in various children
47                         e.g. float:  float a mult int b -> a.mult(floatfromint(b))
48
49                 Matching of infix to operator done at compile time.
50                 thus not usable in very generic functions
51
52 Subjects
53  an object may have multiple orderings. i.e. subtype of ordered(thing) for various things.
54         may even be subtype of ordered(X) for specific X twice.
55  
56  This subtyping is not so much what-it-is, but how-it-behaves and, like people, it may
57  behave differently in different circumstances
58  This is almost a HAS-A link - it HAS-A behaviour.
59  So how do we tell a routine to sort an array of things based on a particular behaviour.
60  One could make an object with a compare fn which takes to things and compares them,
61  and have a different object (class) for each behaviour. But that is rather gross.
62   What is really required is to tell the sort routine what message to send.
63
64 Object creation
65   This is a really interesting issue.
66   Who creates an object: presumably the class...
67   when we convert an int to a float do we
68         1/ anint.convert-to-float - i.e. call an operation on the int object
69    or
70         2/ float.createfromint(anint)  - i.e. call a create operation passing the int as arg.
71
72   For funcitonal languages, where objects are immutable, create must able to create all objects.
73
74 Extending a class
75   it may be desirable to define new functionality for a given type of object, function which
76   are defined in terms of the objects behaviour, not its implementation.
77   Adding functions normally requires subtyping, but  what we are saying that that the new function 
78   are a logical extension of the object. we are just elaborating what was already there.
79   e.g. int.isprime
80   to do this we define a new type which is a subtype and provide the implementation as a statement
81   that the new type elobarates, rather than refines, the old.
82    e.g. stat-real elaborates real
83   this would (almost) imply that
84         GLB(stat-real, float) elaborates float
85
86
87 Example:
88   integer:
89     integer is unimplementable as it is infinite, and some values will not fit in virtual memory.
90     However, many useful subsets of integer are implimentable.
91     We want a supertype which means "integer, or useful subtype thereof"
92     As some ops will overflow, we define the set of possible value to be the integers plus "overflow".
93     define e.g. Z(m)  a+b -> overflow if a or b is overflow
94                           -> (a+b) if a and b and a+b are < m in abs value
95                           -> (a+b) or overflow if a or b or a+b > m in abs value
96        then if m > n then Z(m)+ is more specific then Z(n)+, so Z(m) is a subtype of Z(n)
97        yet we normally consider a smaller set to be the subtype...
98
99     integers and type subsumption:
100       one view of subtyping is that an object of a particular type can be used
101       when an object of a higher type is expected (because it IS of that type too).
102       If an 8bit integer is considered to be a subtype of a 16 bit integer, then
103       we would expect "if x.lessthan(200) then x.add(200)" to not overflow
104       But no....
105       If 16bit is subtype of 8bit, then will work.
106       anything an 8bit can do, a 16bit can do..
107       But while the object may be capable, the value might not be suitable.
108       ..but with "overflow" in our model, any value is suitable, though it might be overflow...
109
110       alternately, overflow might be modelled as an exception. i.e. the op does not return.
111           Z(m)  a+b -> (a+b) if a+b < m in abs value
112                     -> exception otherwise
113       then if 8bit is subtype of 16bit... no real difference
114
115       Want to say: 16bit.add(a,b)  where a,b are subtypes of 16bit, result is 16bit
116            may still overflow, but there wont be any surprises.
117
118       So: Z(n) is the type/set of integers less than n in abs value.
119           operations are limited - maybe decimalise, isprime, isodd
120           Various classes exist which can create Z(n) by adding, multiplying etc.
121           these require arguments which are of a subtype.
122         To facilitate this, we want to be able, given a variable of a type, automagically choose a
123         class which is of that type.
124         If V is Z(100), want to choose (maybe) class Z(127) == signed(8).
125         ouch - we are upside down again...
126         values subset one way, types subtype the other
127
128 Challenges: 
129   output formatting
130   point/colour point??
131   min
132   - find that paper about open/closed self -
133   binary operators - arithmetic.
134   ...
135
136 output/printing
137    This is often one of the hairiest parts of a language because various types want to
138    be treated in similar ways, and people like to avoid extra syntax. 
139   
140    There seem to be three inputs to a formatting request:
141     1/  the objects (values) to be formatted
142     2/  the detailed shape of the formats for each object (hex/decimal field width etc)
143     3/  the constant padding, and the ordering of the formatted values 
144                                 (which is only almost always constant)
145       
146     some parts of 2 are closely tied to 1, some to 3.
147         e.g. field width is probably 3's domain. but is useful with 1 to print part of a string.
148     keeping the inputs separate hazards consistant update
149     keeping them together hazards abstraction and maybe readability.
150     Thus a choice is probably appropriate. Let the programmer decide.
151
152     maybe 
153         stdout.print("now is the ", time, " for ", all," ", good, " men to come to that aid of the ", party)
154                 where   time = now.asciitime(),
155                         all = people.count.decimal,
156                         good = if (random > 0.5) "good" else "bad",
157                         party = "labour";
158       But:
159        hard to distill this format into a per-language file. leaves too much un answered.
160
161     different formats of a value are a bit like different subjects looking at an object.
162                 "you think it is an integer, but I think it is 32 bit hex, uppercase"
163      so I might define "Address" which is an elaboration of int which defines
164         tostr as .hex(8,"0").toupper
165
166 The numerical paradox
167   n-bit integers seem to subtype 16bit is a subtype of 8bit
168   subranges subtype 0-255 is a subtype of 0-65536
169
170   why?
171   A distinction between objects (concrete) and values (abstract).
172   look at casting in C - (int)float preserves value, (int)point doesn't really.
173    (int)char certainly doesn't.
174   
175   or 16bit type defn from above somewhere includes all 32bit and 64bit objects.
176    an 8bit 5 is different from a 32bit 5 etc.
177    but 5 IS 5.0 IS 5.00 
178    if we start treating objects differently from values, we are losing abstraction.
179  
180    So we want the compiler/language to determine which representation is appropriate
181    and how to perform an operation.
182    Probably the most difficult to specify is dealing with loss of precision, as it is 
183    expected. overflow, and to lesser extent underflow, can be deliberately avoided.
184
185 Intrinsic types.
186   What types are INTRINSIC to a language.
187
188    1/ Boolean  essential for decisions.
189    2/ Code - may be third class, but must exist.
190    3/ lamba- again, often of a low class
191    4/ sequence - as in args to a procedure, statements in code, subobjects in an object
192               nice to make this first class - very parameterised, anonymous type.
193         also bits in an integer?
194         Hmm <'cart,x,y> <'polar,r,theta>
195         or imaginary.cart(x,y)  imaginary.polar(r,theta)
196
197 Precision in types
198    To what extent should type of variables be declared?
199      for very local variables which are assigned once, e.g. for loop variable,
200      it seems unnecesary to declare type. just keep scope local and deduce type from usage.
201
202    even at larger level, is "int" enough, or do we want "count" "label" "area" ...
203
204
205 Multi-threading.
206  problem of locking - protecting against unwanted concurrent access.
207  2 senarios - within and without.
208
209  within the methods of an object, the object may occasionally violate the invarant.
210   While the invariant is violated, the object must be single threaded.
211    Dangerous code segments could be bracketed somehow.
212
213  without an object, we may want to use an object assuming conf->mirrors[i].that we are only user.
214   i.e. singlethread is a behaviour we want, so we include it in required type
215    or argument objects.
216
217  How to specify fork/join.
218    don't want it to be tooo automatic or we cannot have fine control.
219    maybe model threads of control as objects - have arrays of them etc??
220
221 Parsing.
222
223  Parsing is a very common sort of problem which must be very configurable.
224  wan't some wway to specify a parser - as a list of parsing objects?
225  const-string might be "extended" to have a parse method which matches the string.
226
227
228 Executables as objects?
229
230  for uniformity, as well as expressivity, it would be nice if executable code
231  were treated like an object - was sufficiently first class to be passed around.
232  Then
233         IF a THEN b ELSE c FI
234  would be a.choose(b,c)
235  where true.choose(x,y) == x.execute
236  and   false.choose(x,y) == y.execute
237  or maybe it would be   
238           a.choose(b,c).execute
239  with obvious redefinition of true and false.
240    a;b   would be a sequence object.
241   {sequence}.execute would be {sequence}.head.execute, then {sequence}.tail.execute
242  need some input to .execute, and some output.  This is looking very functional...
243
244  "normal" lang have code elements which access/modify "local variable".
245  such code elements would have limited scope and so could not be stored in variables
246  of greater scope.  if scope is a part of a variables/values "type" then this can be
247  a type constraint.
248  naturally, code elements could be created which have global scope. This needs a lamba 
249  abstraction.
250
251  methods have the scope of an object, and are assigned to fields in that object.
252  Is each procedure (block?) call a creation of an object? like Beta?
253  Calling a method creates an object with fields which are the arguements and local vars,
254   enstacks the object, and proceeds to execute the .code sequence.
255   The objects in a .code sequence are method calls. Each identifies a target object, a
256    target method of that object, and a list of objects as arguments.
257  OR
258    an object maps a methodname to a method.
259    a method maps an object to a (more specific) method.
260    eventually (After all args collected) a method maps an object to an object.
261    Hmmmm. an object maps a methodname to a method which is a new scoped execution object.
262    given an arguement, this executes.
263    That sees procedure parameters as a single sequence.
264
265  This is a bit wishy washy, but seems to tend toward a nice simple execution model...
266  What do I particularly want:
267    scope executable which can be passed down/around and optionally executed later.
268    unscoped lambda expression - i.e. an independant object!
269    combination - a scoped lambda expression.
270
271  BUT: What are the semantics of an atomic execution. is it value transformation ala functional
272       lang, or state change (of some scoped/stacked object) or both?
273
274
275 Subtyping objects is an illusion.
276   Subtyping of values makes lots of sense. Values don't change.
277   Subtyping of mutable objects just doesn't work. The objects of the sub type
278    must behave like objects of the supertype, and hence be subject to any change
279    that the supertype may be subject to.
280    Thus the invarient can only become less restrictive, thus allowing more value.
281    This is the integer subrange vs n-bit int distinction again.
282
283   So with typing, we focus on sub-types of VALUES of objects, and
284    type function to express types of objects.
285     The value of an array of ints is a subtype of the value of an array of objects,
286     but an array-of-ints object is a restriction of an array-of-objects object.
287    Clearly parameterised classes will play a bit role here.
288
289 SubObject references.
290   It is often desirable to have a pointer into a bag object such as a
291   linked list, a skip list, etc.
292   This is more than just a handle on a subobject as it may be used to
293   navigate around the structure.
294   Particularly in a multi-thread envronment, the bag object needs to
295   keep track of what active pointers there are too its sub objects, so
296   it can guard against deleting/changing an active object, or maybe an
297   object on an active path.
298   Requiring the client to "release" a reference is as bad as using
299   malloc/free. It is better to have language support - e.g. though
300   reference tracking. References must be released when pointers are
301   destroyed, and it is best if language system guarentees this.
302   This is like memmory allocation problem, except that a garbage
303   collect approach won't cut it.
304
305   Could possibly have several classes of references e.g. readonly and
306   read-write and ways to promote/demote them.
307   There is also a question of cutting a object up (e.g. double linked
308   list) and how that is type checked.....
309   Also, I like having a pointer to a thing that could be in one of
310   several doubly linked lists, and I don't care which one.
311   If I don't know, the compiler wont know, so how is concurrency
312   guarded...
313
314
315 Objects without inheritance.
316   I have a feeling that when separated from subtyping, object
317   inheritance is purely an implementation convenience.
318
319   This convenience is possibly confusing and might be better
320   discarded. We can simply use object inclusion (has-a) and let the
321   compiler determine that a subobject can be inlined.
322   methods for the new class can be equated to methods on the sub
323   object or, quite naturally, a new method with calls a method on the
324   subobject. This discards super. calls and removes any name confusion
325   with multiple inheritance.
326   A question is self. calls. This is (after all) the most interesting
327   thing in oo programming. The routine in the superclass calls a
328   method in the subclass (which may, or may not be the same class).
329
330   One answer is my idea of extension classes which implement new
331   methods on objects of some known type interms of the external
332   interface to that object. e.g. sine(x) in terms of plus/mult/div etc.
333   Q. to what extend with the object be mutable??
334
335 Question. are safe downcasts needed. Are they like typecase in
336   modular-3? but there may be subthings you don't know about.
337   Should not you extend each possible subclass with the necessary
338   method. can this be done post-hoc.  Is this just needed because
339   programmers don't really understand subtyping??
340
341   Java has an example (probably many) of safe downcasting..
342   A Hashtable is defined which maps objects to objects.
343   When you get an object out, the programmer probably knows the
344   type from the content of the key, but the language doesn't.
345   Hence a safe downcast is needed.
346
347   Two ideas present for making this more typesafe.
348   [ note safedown cast is not "typesafe" because it can through an exception]
349   1/ The key to the hash table could be
350         (key,type-of-content)
351      So store(key:object, ctype:type, content:ctype)
352      and  fetch(key:object, ctype:type) : ctype
353
354   2/ The type can be explicitly stored with the content (instead of implicitly)
355      Then the table entry would be
356         <key:object, ctype:type, content:ctype>
357      It would be in either case.
358      
359    This requires that types, or at least classes, exist as objects.
360    Q. are classes enough, or are all types potentially needed as objects?
361    we would really want a partial ordering, so all types are needed.
362
363 The next question is: who owns an operation like addition?
364   Addition of integers is a function of the set of integers (Z) more
365   than of any particular integer. 3.plus(4) always looked terribly asymetric.
366   If we think of objects more like values (which is pleasing for
367   numbers), then there are possibly many things we could mean by
368   "plus", modular arith for example.
369   Real-plus is the *same* op as integer-plus (as an integer IS a
370   real), but what about float-plus?
371   float is a REAL problem (joke!) because people want to treat it like
372   a real, but it simply ISN'T real (more-so than int isn't integer).
373   Possibly the semantics could be that a+b yields "real" addition, but
374   this value - which cannot be stored - gets converted to whatever it
375   gets stored in. e.g. a float or an int, which an implicit but
376   clearly acknowledged possible loss of information.
377   This doesn't quite work with nested expressions, as a difference of
378   two very close large numbers looses a lot of precision. We simply
379   cannot keep infinite precision (or even adequate precision)
380   intermediates.
381
382   I think I've lost the thread a bit though. That is a question of
383   overloading '+' and how to resolve that overloading.
384   ... but is it the same problem?
385   
386   A problem with associating plus with "int" rather than "3", is that
387   if we have an object that we don't know is an int, how do we add to
388   it.
389   Well, we must know that it is of a type that supports add (is that
390   ring? - probably ring-of-X) i.e. generic addition must be through
391   parameterised genericity rather than subtype genericity. (actually,
392   it's probably additive-group rather than ring).
393  
394   Lets practive that:
395    We say  "X == Additive-group of type X" is a type which supports the
396   binary operation "plus", thus is A and B are both of type X, then
397   "plus(A,B)" is of type X. (Additive-group "extends" X)
398   Then we can define an additive group of type "int", "float",
399   "matrix(n,m,scalar)",  "0..6", where for each we must specify how
400   addition works in each case.
401   We can say that "X is an Additive-group(X)"
402
403   But if we see "plus(3,4)", what type is that? is it int.plus or
404   float.plus or "0..6".plus?  If we want 3 to be simply the value "3",
405   equal in types 0..6 and int and float, then the plus must be decorated,
406   or the type must be propergated down from the receiving method(????)
407
408   If we use primarily one additive-group at a time, something like a
409   with-clause would suffice for briefness. But we may well be mixing
410   ints with floats, or anything else, and an accidental expectation of
411   int rather than modulo semantics would be confusing.
412   
413   Maybe a low-cost with-clause on a per-expression basis:
414     int(3+4 div b)  float(3/b+4/f)  Zseven(4+5)
415   Without such clause, the least surprising would be used - int.plus
416
417   For non-operator methods, this isn't an issue. Just include type in
418   name.
419
420   Rewind... When we say "X is an Additive-group of X", we need to
421   include the "of X" because if Y is a subtype of X, "Y is an
422   Additive-group of X", but probably not "of Y". or more importantly,
423   "of X" is more useful than "of Y".
424
425
426 An assertion: (did I make this earlier?)
427   subtyping mutable types doesn't make sense. Only subtyping of
428   immutable values.
429   The rationale is that the important use of subtyping is: is A  is a
430   subtype of B, then a member of A can be used where ever a member of
431   B can be used.
432   Thus any change that is legal to a member of B MUST be legal to a
433   member of A, and the B-visible change will be the same.
434   Thus A must maintain the same state, and can only extend it with
435   more information. Yet B-acceptable changes will not usefully affect
436   the extra information......
437   Maybe not. A could contain a change history
438   Lots of other examples. A shape that can change colour...
439
440   So we can reasonably subtype all types.
441
442 Want to motivate result type being function of arg types.
443   choose(a,b:object) -> lub(a,b)
444   choose(a,b)+1 ->  lub(additive-group/a, ag/b)
445    maybe say union rather than lub.
446   double(a) -> type-of(a), but what does that mean?
447   must choose significant point in type lattice between root and 2*a.
448   this probably what groups are about, but want more examples.
449   hmm. type info is static. this worth remebering. it is exactly what
450   is important.
451   
452
453 HereWeGoAgain
454
455 An "Object" is a "thing" which has "behaviours".
456 By "thing" we mean that it is something that can be held (references, pointed to).
457 It is a bit like a black box.
458
459 Behaviours include (at least) responses (reactions).
460 A response is elicited when we send an(other) object to the object.
461 The response was three parts:
462         It produces an object.
463         It (may) change the original object into a different object
464         It may send other objects to other objects thereby causing other
465            objects to change into different objects.
466
467 So far it is pretty confusing. We need some structure.
468
469 A "type" is a set of "objects".
470
471 types will usually be prescriptive (is that the right word) meaning that any object which
472 fits the description is a member of the set.
473