Showing posts with label interface. Show all posts
Showing posts with label interface. Show all posts

2011-02-28

self as used by interfaces and anonymous algorithms

2.28: adda/lexeme/self/for anon'algor's and interfaces:
. the word"self is useful in 2 contexts:
# anonymous algorithm:
it means the current algorithm,
# type`interface:
it means a current instance of that type;
eg, t.type: ( self!: defines a postix operator).
. if there is an algorithm in the header
(eg, to declare algorithms that won't change
for some reason...)
then the usual scope rules prevail .

2010-12-30

optional ducktyping

adda/oop/optional ducktyping:
12.28: syntax:
. instead of optional typing,
what about optional ducktyping?
. the easy way to declare a local
is to have it's first use describe it's type;
ie, its declaration can double as its first use;
eg, v.t -- declares "(v) to be of type"(t);
and thereafter, the var's type ext is optional;
eg, v -- the var whose full name is v.t .
. in the case of ducktyping,
the first use has the null type;
eg, ( var. ) -- the dot at the end
assures the parser that you didn't
forget to specify the var's type;
rather, you want a ducktype compiled;
ie, the parser is to find the list of
operations that were applied to that var,
and declare that to be the var's interface;
eg, f(var.); g(var) .
-- that says var is a ducktype,
and its interface is: f(), g() .

12.28, 12.30: other:
. how are typed and ducktyped obj's interacting?
both {types, ducktypes} have type.tags;
but whereas a ducktyped object
carries the type.tag with its value,
the statically typed var stores its tag
in the local symbol table
of the subprogram where it resides;
ie, the symbol table storing a ducktyped var
will declare its type as null,
meaning to be delivered at run time .
. the type.tag is a pointer to the var's type mgt
which will have a dictionary of operations .
. during run time, the ducktype's type mgt is then
checked for having all the expected operations .

# a typed obj assigned to a ducktype:
needs to be wrapped in a type.tagged box,
ie, ducktyped obj = (value, type.tag);
and statically typed obj = (value) .

# a ducktyped obj assigned to a typed obj:
needs to be unboxed before assignment
(the type.tag is compared to the destination's expected type;
and, if compatable, the type.tag is stripped out,
and the remaining value assigned).
. the assigned ducktyped obj
then still virtually has the same type.tag,
only its statically in the symbol table
rather than dynamically beside its value .

review of the current stacking system:
. static types can help efficiency:
if a parameter is statically typed,
then the type's mgt can assist in
the typical amount of stack space
needed by the union of its variants
otherwise, the system can only plan on stacking
# a ptr to trailer (local heap); or,
# a ptr to readonly .

12.30: binary operations (biops):
. just like (statically) typed var's,
ducktyping can involve class clustering
where a biop's arg's can be ducktypes;
in these cases, the run-time is checking
that both arg's have a common supertype .
. an extension of that idea is where
any number of arg's can be accommodated:
# by checking all for a common supertype;
# by checking every arg's type for the presence of
a function with a compatible signature .

2010-04-30

binary operator support for evolvers

4.25: adda/oop/biop'support for evolvers:

. unlike polymorphs such as type"number,
when an evolver gets a biop (binary operation),
it doesn't have a type'mgt that knows
who all its subtypes are,
so it doesn't know how to do conversions,
and can't delegate a biop call
to a particular subtype .

. one approach, though not generalizable,
is to have all biop methods be defined by
the root type,
and defined in terms of unary operations .
. all evolutions of that root type
would then inherit a working biop,
even if they had defined their own unary op's .

. the unary op's should provide code too,
just to be consistent?
ie, evolver subtyping involves complete impl'inheritance ?
[4.30:
. it should be up to the individual root.type
as to whether or not it chooses to
share a given method;
but if it wants the biop's to work
the way they do for polymorphs,
then it will provide the methods for all biop's .]

. a dynamic scripting approach,
like one might expect from a lisp system,
would be where all evolutions or subclasses
are allowed to read and modify
a supertype's biop-managing script .
. a subtype would register itself
and complete a table:
subclass x subclass x biops;
or, do whatever other rescripting was needed
in order handle the various combinations of subclasses
that are sent a biop message .

. a strategy for how to design evolvers
is to keep in mind why inheritance is good here:
it offers a form of type-checking
along with interface-based programming .
--[4.29: it offers nominal in addition to
structural subtype polymorphism (generics).]
. generics is when any type will do
if it supports the same interface
(I call these typeless obj's "(generals)).
. nominal type checking includes
the given type'name and all its descendants .
1130:
. the type'tag points to type'mgt
which is a node in a tree (or lattice);
that node has ptr's to all sources of inheritance .
. the 2 arg's of a biop must share
one or more supertypes,
and one of the supertypes must support that biop .
. if more than one?
[4.29: as when using multiple ada`packages,
the biop could be qualified to indicate
which node in the type.class lattice
the operation should be executed by .]
[4.30: qualifying an infix operator
could look rather confusing;
another option is raising an exception when
multi-inheritance is getting ambiguous .
. Ada05 allows multi-inheritance only with
interfaces (methods are not inherited,
and there's no concept of a biop).]


4.29: adda/oop/evolvers supporting biop's:

. what if an evolver wanted to inherit from a polymorph?
as long as adda promotes generics or interfaces .
[4.30:
. inheritance that expresses a
nominal subtype polymorphism
may not be good for contract-based prog'ing:
. types that support the same interface
could be modeling very different things;
so there should be a distinction made between
whether the model or the interface is supported .
eg, when I say the formal is a number,
I probably don't mean
the assigned obj'should do clock arithmetic
-- even if the interfaces are the same .]

. how does it support biop's ?
it needs to ask both arg's who their type'mgt is,
and see if they have a common superclass,
then see if any of them have a method for that biop .
but, num is a closed type, (not an evolver):
the biop it supports is not tolerating any
unrecognized subtype names .

. similar to the idea that there are
separate inheritances for interface and impl',
not every interface inheritance
has to imply the type is compatable with
the one it inherited from .

. just as polymorphs have some way of cooperating
in order do binary operations on various subtypes,
the evolvers need some universal way of describing value:
ie, the one job of the root.type
is having a way to define the supported values
in terms of some composition of public types;
[4.30: ie,
a subtype doesn't have to reveal how it stores a value,
but it does need to support exporting of a value
in some public form,
similar to offering a printed version
but instead of exporting as text,
it would be an efficient binary form .]
. for example,
number could describe its polymorphs
as an evolver would:
instead of subtypes knowing each other
and providing conversion routines,
the root.type, number,
could define a record of integers
(or a pointer to symbol in one case)
that describes all the parts of any number:
( mant'int#, [irrational]/ -- mantissa
, mant'frac'numerator#
, mant'frac'denominator#
, exp'int#, exp'frac# -- exponent
, sign'int#, sign'frac# -- large for complex numbers .
); [4.30:
. for types that are not numeric,
the root.type could express itself as
some tree of certain classes of symbols,
like the way english can be described,
with a grammar and a vocab' .]

. is that idea useful for the problem of
integrating popular notions of oop with biop's?

. the obj'c oop is assuming privacy from
even subclassers, not just clients;
therefore, any biop's must be defined in terms of
the superclass's unary op's .
. as shown by class"numbers,
there will be situations where only a
universal value format will be useful:
the biop will ask both arg's
to convert themselves to universal,
and then after working on a pair of univerals,
the biop can ask the receiver
to convert the universal to the type prefered;
[4.30: ie, within an evolver class,
one of the subtype's assignment functions
is expected to accept a universal-formatted value .]