7.4: adds/security
/when software capitalists become dictators:
. we see what a mess engineers have made of
the internet and computer security;
as chips make more decisions in our appliances,
they are like new laws imposed upon our nature;
this is where capitalists would be legislators;
and they must therefore submit to our constitution:
ie, representatives are elected,
initiatives can be brought by the people
and laws are open to public scrutiny .
. not only is opensource software not communism
(Bill Gates was misquoted as suggesting this);
but software as private capital
is sure to present an inevitable tyranny
just like a communism will
without the checks and balances of
democracy and separation of powers .
7.15: adds/robot/constitution with context casing:
. one way to balance private and public interests
is by including a context chip,
which has the ability to override other chips
whenever it senses the robot is on public property .
. it would also have final say over
the use of force the public is interested in .
2011-07-30
TDD (Test-Driven Development)
web.adds/sw.dev.process
/TDD (Test-Driven Development):
7.1:
"( my python web app is obs ! )
"( you forgot your TDD unit tests, pal )
. what is TDD? Test-Driven Development
TDD != Unit Testing Dave Rolsky 2009
7.5: synth:
. in test driven development,
rather than ask "(how to impl this feature?),
we ask "(how do you prove
that a feature is impl'd?)
-- and that drives your interface design
(ie, the tests are designed even before
the interfaces, not just the bodies).
links:
sw.dev.process @ wiki
Xunit options for obj'c
agilepainrelief.com:
. the unit test tries to verify
all features of a given module;
tdd (Test-driven development) is about
using tests as documentation:
. assuming you already have
libraries of utilities and datatypes,
you design the interface first
then the tests, and finally the bodies
that will make the tests pass .
. if you are writing your documentation first;
then you won't have any problems with also
writing test harnesses before the app is built .
. this is supposed to complement prototyping:
the developer often needs a semi-working model
to get ideas for a more polished model .
. the prototype is then used as the basis
for a high-reliability app
that writes the final design as a set of
user doc's, unit tests,
maint'doc's, feature tests,
and functional tests (having each function
beginning with precondition testing
and ending with postcondition testing).
. reverting to the last version that passed all tests
may often be more productive than debugging.
instead of relying on platform services directly,
they should be accessed through a wrapper,
so that functional testing can be applied .
--
See dependency inversion principle
/TDD (Test-Driven Development):
7.1:
"( my python web app is obs ! )
"( you forgot your TDD unit tests, pal )
. what is TDD? Test-Driven Development
TDD != Unit Testing Dave Rolsky 2009
7.5: synth:
. in test driven development,
rather than ask "(how to impl this feature?),
we ask "(how do you prove
that a feature is impl'd?)
-- and that drives your interface design
(ie, the tests are designed even before
the interfaces, not just the bodies).
links:
sw.dev.process @ wiki
Xunit options for obj'c
agilepainrelief.com:
I’ve been on projects where we tried to writeunit testing vs Test-driven_development
all of our tests after the classes were written.
Our test suite was valuable
and prevented many regressions.
But it allowed many issues to slip through.
Weaker elements in API’s were often missed
and were changed only at a later date
at some expense.
Tightly coupled code was allowed to evolve
making some elements of the application
very difficult to test
without having to create dozens of
other (often unnecessary) objects.
As a result of all this
it became more difficult to write test cases over time.
Would TDD have solved all of these problems?
Perhaps not but it would have forced us to
confront many of them sooner.
. the unit test tries to verify
all features of a given module;
tdd (Test-driven development) is about
using tests as documentation:
. assuming you already have
libraries of utilities and datatypes,
you design the interface first
then the tests, and finally the bodies
that will make the tests pass .
. if you are writing your documentation first;
then you won't have any problems with also
writing test harnesses before the app is built .
. this is supposed to complement prototyping:
the developer often needs a semi-working model
to get ideas for a more polished model .
. the prototype is then used as the basis
for a high-reliability app
that writes the final design as a set of
user doc's, unit tests,
maint'doc's, feature tests,
and functional tests (having each function
beginning with precondition testing
and ending with postcondition testing).
. reverting to the last version that passed all tests
may often be more productive than debugging.
instead of relying on platform services directly,
they should be accessed through a wrapper,
so that functional testing can be applied .
--
See dependency inversion principle
Labels:
adds,
sw.eng,
unit testing
including obj'c features
7.23: adda/oop/including obj'c features:
. in the expression"( a`b(x)`c ),
the ( a`b(x) ) means
the object"a has a procedure b(x)
that returns an object location
whose available functions include c .
. the syntax"(a`b) is not necessarily
involving self-modification;
it simply means subprogram"b has access to (a)
as an inout parameter
(the subprogram's object parameter).
. is there some efficient way of doing a`b`c
without passing pointers ?
I was thinking there was some virtual way
that doesn't really need pointers
(oop doesn't really need
all the pointers it thinks it needs)...
. if a subprogram's object param
returns a reference to something other than
the object param,
then in the c translation of same
this subprogram takes a destination param;
ie, a param that inputs a destination address
showing where the caller wants the return placed .
. why wouldn't it always take a destination param
even when returning self? ...
because the caller is already housing that obj .
7.26:
. my original concern here
was allowing the passing of references
and the use of object param's,
just like obj'c oop does,
while still using the sort of oop system
that did not generate garbage .
todo:
. I think obj'c has the convention that
even if ( a`b(x) doesn't return anything
if an object reference is expected as a return,
as is the case in "( a`b(x)`c ),
then it will use a reference to (a);
ie, ( a`b(x)`c ) would equal:
( a`b(x); a`c ) .
. in the expression"( a`b(x)`c ),
the ( a`b(x) ) means
the object"a has a procedure b(x)
that returns an object location
whose available functions include c .
. the syntax"(a`b) is not necessarily
involving self-modification;
it simply means subprogram"b has access to (a)
as an inout parameter
(the subprogram's object parameter).
. is there some efficient way of doing a`b`c
without passing pointers ?
I was thinking there was some virtual way
that doesn't really need pointers
(oop doesn't really need
all the pointers it thinks it needs)...
. if a subprogram's object param
returns a reference to something other than
the object param,
then in the c translation of same
this subprogram takes a destination param;
ie, a param that inputs a destination address
showing where the caller wants the return placed .
. why wouldn't it always take a destination param
even when returning self? ...
because the caller is already housing that obj .
7.26:
. my original concern here
was allowing the passing of references
and the use of object param's,
just like obj'c oop does,
while still using the sort of oop system
that did not generate garbage .
todo:
. I think obj'c has the convention that
even if ( a`b(x) doesn't return anything
if an object reference is expected as a return,
as is the case in "( a`b(x)`c ),
then it will use a reference to (a);
ie, ( a`b(x)`c ) would equal:
( a`b(x); a`c ) .
Labels:
adda,
dev.obj'c,
obj'c,
oop,
translation
protecting the stack limits
7.22: adda/protecting the stack limits:
. how can one test for stack limits per platform?
if you test it once per platform
could the limit become smaller later?
it could depend on number of processes,
and current ram count ?
the user or an error could downgrade ram .
some help from addm:
. one thing that helps the stack problem
is assuming that user programs are addm code
rather than native code;
addm uses the c stack in a very limited way
and puts the user's stack entirely in the heap;
the user does call standard libraries
that in turn are native code;
but these can be designed to conserve stack space
(eg,
all recursive routines are finding some way to
serialize the large jobs;
eg, instead of giving gig's to quicksort,
the sorter breaks the job into mbyte sections,
and gives the quicksort's sections to mergesort ).
...
but can't the user can program natively? yes:
(see adda/natively coded extensions)
the user isn't restricted to addm,
so adda must be aware of some stack limits
and provide protections against overflow .
. how can one test for stack limits per platform?
if you test it once per platform
could the limit become smaller later?
it could depend on number of processes,
and current ram count ?
the user or an error could downgrade ram .
some help from addm:
. one thing that helps the stack problem
is assuming that user programs are addm code
rather than native code;
addm uses the c stack in a very limited way
and puts the user's stack entirely in the heap;
the user does call standard libraries
that in turn are native code;
but these can be designed to conserve stack space
(eg,
all recursive routines are finding some way to
serialize the large jobs;
eg, instead of giving gig's to quicksort,
the sorter breaks the job into mbyte sections,
and gives the quicksort's sections to mergesort ).
...
but can't the user can program natively? yes:
(see adda/natively coded extensions)
the user isn't restricted to addm,
so adda must be aware of some stack limits
and provide protections against overflow .
symbol table linking
7.14: 7.15: adda/symbol table linking:
. etrees (expression trees)
are tree nodes with pointers into
global and local dictionaries of symbols
(symbol tables).
. every etree module
implies access to a global symbol table,
and must specify any needed local symbol tables .
. there can be more than one local symbol table;
because, a dictionary can include procedures;
and, procedure definitions can have
local dictionaries:
the parent procedure becomes the
scope of its local dictionary,
hence the term "(nested scopes),
involving stacks of local symbol tables .
. each module has a tree of symbol tables .
. a typical scope path is:
module/subprog/nested sub/nested block/nested block .
. the 3 main uses of "(library) include
system, standard, and custom .
. the system library of an addx installation
is a service for organizing and linking
the modules that are available for reuse .
. a standard library is a module that is
declared by the system's language .
. a custom library is one added by the user .
. each module has a list of imported modules,
and a tree of symbol tables
to match its tree of nested scopes .
. when designing the pointer that is
going from etree nodes into symbol tables,
there must be an efficient coding,
and it should support efficient copying
even when it involves context changes
(re: adde/object copy & paste).
etree node variants for library symbols:
. there is first a bit to distinguish
symbol location type in {library, local}:
# library location:
. there may be many libraries in use (15-bit),
and many symbols per library (16-bit) .
# local location:
. there's often no more than
4 nested levels of locals (2bit);
and often less than 256 symbols per local (8bit).
but if node`size is in increments of 16bit chunks
that division could be 4 bits for 16 nested scopes,
and an 11-bit space for locals,
or less if the descriminant is more than 1 bit .
[7.30:
... in any case, the more space you save,
the less efficient it is to remap etree nodes
to a new symbol table after a context change .]
details of library location:
. there could be an infinity of libraries over time,
so the library codes in an etree node
don't represent specific libraries,
rather they represent a slot in the module's
list of imported or required libraries;
however, standard libraries can be specified,
since there are a finite number of them;
ie, if the code is in the range that is
reserved for standard lib's,
then that is the same code used by
the system library;
otherwise, we need to use the module's import list
to convert the symbol table's code
into one that the system library recognizes .
. the system library creates a custom lib's code
by taking a Secure Hash of its interface
. as long as that didn't change,
it would be considered the same library .
. etrees (expression trees)
are tree nodes with pointers into
global and local dictionaries of symbols
(symbol tables).
. every etree module
implies access to a global symbol table,
and must specify any needed local symbol tables .
. there can be more than one local symbol table;
because, a dictionary can include procedures;
and, procedure definitions can have
local dictionaries:
the parent procedure becomes the
scope of its local dictionary,
hence the term "(nested scopes),
involving stacks of local symbol tables .
. each module has a tree of symbol tables .
. a typical scope path is:
module/subprog/nested sub/nested block/nested block .
. the 3 main uses of "(library) include
system, standard, and custom .
. the system library of an addx installation
is a service for organizing and linking
the modules that are available for reuse .
. a standard library is a module that is
declared by the system's language .
. a custom library is one added by the user .
. each module has a list of imported modules,
and a tree of symbol tables
to match its tree of nested scopes .
. when designing the pointer that is
going from etree nodes into symbol tables,
there must be an efficient coding,
and it should support efficient copying
even when it involves context changes
(re: adde/object copy & paste).
etree node variants for library symbols:
. there is first a bit to distinguish
symbol location type in {library, local}:
# library location:
. there may be many libraries in use (15-bit),
and many symbols per library (16-bit) .
# local location:
. there's often no more than
4 nested levels of locals (2bit);
and often less than 256 symbols per local (8bit).
but if node`size is in increments of 16bit chunks
that division could be 4 bits for 16 nested scopes,
and an 11-bit space for locals,
or less if the descriminant is more than 1 bit .
[7.30:
... in any case, the more space you save,
the less efficient it is to remap etree nodes
to a new symbol table after a context change .]
details of library location:
. there could be an infinity of libraries over time,
so the library codes in an etree node
don't represent specific libraries,
rather they represent a slot in the module's
list of imported or required libraries;
however, standard libraries can be specified,
since there are a finite number of them;
ie, if the code is in the range that is
reserved for standard lib's,
then that is the same code used by
the system library;
otherwise, we need to use the module's import list
to convert the symbol table's code
into one that the system library recognizes .
. the system library creates a custom lib's code
by taking a Secure Hash of its interface
. as long as that didn't change,
it would be considered the same library .
natively coded extensions
7.22: adda/natively coded extensions:
. the adda compiler helps turn adda code
into obj'c code,
and then the user plugs that into xcode
to generate mac programs .
. there are 2 styles of user programming:
# extending addm:
. the user want's their library unit to be
seen by addm,
so that user's library unit is callable from
user's other scripts .
. this entails compiling the library unit,
recompiling addm to bind with the library unit
and relinking addm with the entire library .
. this is known as pythonic development:
a module is run as translated vm code
until it's perfected:
then it's promoted to native code
and made available in the account's library .
# building native apps:
. in building a native app,
adda code is translated to the native lang
(eg, mac speaks obj'c & cocoa).
. the native program then imports
the relevant adda libraries
and includes addm as a component
so that the program or its user
can run arbitrary adda scripts .
. the adda compiler helps turn adda code
into obj'c code,
and then the user plugs that into xcode
to generate mac programs .
. there are 2 styles of user programming:
# extending addm:
. the user want's their library unit to be
seen by addm,
so that user's library unit is callable from
user's other scripts .
. this entails compiling the library unit,
recompiling addm to bind with the library unit
and relinking addm with the entire library .
. this is known as pythonic development:
a module is run as translated vm code
until it's perfected:
then it's promoted to native code
and made available in the account's library .
# building native apps:
. in building a native app,
adda code is translated to the native lang
(eg, mac speaks obj'c & cocoa).
. the native program then imports
the relevant adda libraries
and includes addm as a component
so that the program or its user
can run arbitrary adda scripts .
Labels:
adda,
architecture
object copy & paste
7.14: adde/object copy & paste:
. the typical copy & paste
is a char-string operation;
whereas, an object selection
is operating over etrees (expression trees)
which are tree nodes with pointers into
dictionaries of symbols (symbol tables).
. there can be more than one symbol table;
because, a dictionary can include procedures,
and procedure definitions can have local dictionaries;
hence, a single etree can be within
the scope of multiple dictionaries
represented by stacks of local symbol tables .
. a copy becomes a module
meaning it needs its own copy of
any local symbol tables;
however, the cost of copying
depends on the destination:
if the paste location is within the source's scope
it shares all the same symbol tables .
. when some symbol tables are
not shared between source and destination
those tables must be copied;
and, affected etree nodes adjusted
to point into the new tables .
. when an arbitrary substring is selected
it can be representing fractions of etrees,
eg, given a+b+c, a selection can include
all of term-b and partials of terms {a,c} .
. there may be parts of the given language where
partial terms don't have the same meaning;
ie, there would be nothing but a
char-string translation of the object selection .
. in any case,
the quickest, most general way to define a selection
is to get links to the entire chain of symbol tables;
and, copy the entire subtree that contains
all the fragments of the selection;
then include a descriptor that shows
where the selection is beginning and ending .
. when would you want fragments and still want
the etree object rather than a char string?
for orthogonality,
we have to provide for the possibility
that one of adde's plug-in app's
can find some use for such a selection;
ie, in many cases of user interaction
the selection is for a function other than
cut or copy .
7.15:
. when designing the pointer that is
going from etree nodes into symbol tables,
there must be an efficient coding,
and it should support efficient copying
even when it involves context changes .
. both the source and destination of a copy
have scope paths:
if the scope paths aren't the same
we have to identify any scopes not shared
and copy their symbol tables
for merging with the destination .
if this is a cut instead of a copy,
there are fewer choices,
since the destination space is smaller .
. a complication of multiple nestings of scope
is the orphaned symbol from ancestor scopes:
these imply some sort of communication with
a context which no longer exists .
. we have to remind the user
that the orphan's place in the destination
may need special attention:
should it be added to the new parent scope,
or some higher scope ?
. the default location would be relative height,
ie, the same number of scopes up the path
as it was in the source location .
. in any case, we have to assist the user
in keeping track of these orphan relocations,
and make sure that all affected contexts
are adjusted to create a sensible communication
such that, the role of the source ancestor
is now provided by the new context's procedure .
. the typical copy & paste
is a char-string operation;
whereas, an object selection
is operating over etrees (expression trees)
which are tree nodes with pointers into
dictionaries of symbols (symbol tables).
. there can be more than one symbol table;
because, a dictionary can include procedures,
and procedure definitions can have local dictionaries;
hence, a single etree can be within
the scope of multiple dictionaries
represented by stacks of local symbol tables .
. a copy becomes a module
meaning it needs its own copy of
any local symbol tables;
however, the cost of copying
depends on the destination:
if the paste location is within the source's scope
it shares all the same symbol tables .
. when some symbol tables are
not shared between source and destination
those tables must be copied;
and, affected etree nodes adjusted
to point into the new tables .
. when an arbitrary substring is selected
it can be representing fractions of etrees,
eg, given a+b+c, a selection can include
all of term-b and partials of terms {a,c} .
. there may be parts of the given language where
partial terms don't have the same meaning;
ie, there would be nothing but a
char-string translation of the object selection .
. in any case,
the quickest, most general way to define a selection
is to get links to the entire chain of symbol tables;
and, copy the entire subtree that contains
all the fragments of the selection;
then include a descriptor that shows
where the selection is beginning and ending .
. when would you want fragments and still want
the etree object rather than a char string?
for orthogonality,
we have to provide for the possibility
that one of adde's plug-in app's
can find some use for such a selection;
ie, in many cases of user interaction
the selection is for a function other than
cut or copy .
7.15:
. when designing the pointer that is
going from etree nodes into symbol tables,
there must be an efficient coding,
and it should support efficient copying
even when it involves context changes .
. both the source and destination of a copy
have scope paths:
if the scope paths aren't the same
we have to identify any scopes not shared
and copy their symbol tables
for merging with the destination .
if this is a cut instead of a copy,
there are fewer choices,
since the destination space is smaller .
. a complication of multiple nestings of scope
is the orphaned symbol from ancestor scopes:
these imply some sort of communication with
a context which no longer exists .
. we have to remind the user
that the orphan's place in the destination
may need special attention:
should it be added to the new parent scope,
or some higher scope ?
. the default location would be relative height,
ie, the same number of scopes up the path
as it was in the source location .
. in any case, we have to assist the user
in keeping track of these orphan relocations,
and make sure that all affected contexts
are adjusted to create a sensible communication
such that, the role of the source ancestor
is now provided by the new context's procedure .
tags, link-trees, and file-trees
7.3: 7.30: adde/tags, link-trees, and file-trees:
. how to integrate tags with folder systems?
placing a file in a folder is tagging it;
a hierarchy is a tag with segments;
ie, each path name is one tag .
. while a file can be in only one folder,
it can be assigned to many tags .
. tags can be thought of as
a list of links to its members;
and, equivalently, as attributes of a file:
each file or file link can list all the tags
to which it is a member,
just as it can tell the folder path it's in .
link-trees vs file-trees:
. a file-tree is the usual folder tree,
it contains actual files rather than links;
so, a file can be a member of only one file-tree .
. the link-tree is like a file-tree
except it contains only links to files
rather than actual files;
thus, a file can belong to many link-trees,
and may be in many places
within the same link-tree .
7.30:
. the main idea for these distinctions
is that file-trees are low-level concerns;
the only reason they need to be accessed
is when the space limits require
deletions or archiving .
. most file system operations
are concerned only with organizing files,
not managing limited space,
and each activity should have its own
customized view of the file system;
so, most file accesses should be done
through link-trees .
. tags can be applied to either files or links,
depending on the tag's scope:
tags on files are global;
tags on links apply only to
a specific link-tree;
ie, each link-tree has its own set of tags:
both the ones induced by the global tags
belonging to files it's linking to,
and the tags specified by the
user of the link-tree .
. how to integrate tags with folder systems?
placing a file in a folder is tagging it;
a hierarchy is a tag with segments;
ie, each path name is one tag .
. while a file can be in only one folder,
it can be assigned to many tags .
. tags can be thought of as
a list of links to its members;
and, equivalently, as attributes of a file:
each file or file link can list all the tags
to which it is a member,
just as it can tell the folder path it's in .
link-trees vs file-trees:
. a file-tree is the usual folder tree,
it contains actual files rather than links;
so, a file can be a member of only one file-tree .
. the link-tree is like a file-tree
except it contains only links to files
rather than actual files;
thus, a file can belong to many link-trees,
and may be in many places
within the same link-tree .
7.30:
. the main idea for these distinctions
is that file-trees are low-level concerns;
the only reason they need to be accessed
is when the space limits require
deletions or archiving .
. most file system operations
are concerned only with organizing files,
not managing limited space,
and each activity should have its own
customized view of the file system;
so, most file accesses should be done
through link-trees .
. tags can be applied to either files or links,
depending on the tag's scope:
tags on files are global;
tags on links apply only to
a specific link-tree;
ie, each link-tree has its own set of tags:
both the ones induced by the global tags
belonging to files it's linking to,
and the tags specified by the
user of the link-tree .
Labels:
adde,
filesystem,
pointers,
vfs(virtual file system)
binary operation aggregation
7.10: adda/cstr/binary operation aggregation:
. biop's (binary operations)
can be seen as aggregated
by a rule book showing combinations of biops
that should be considered to be
one subprogram call
ie, binding to a particular subprogram;
eg, {?, else} are both biops,
and the rule book would say that
(?, else) is a single function:
?-else(truth,proc,proc).proc
or ?-else(truth,fun,fun).fun .
. biop's (binary operations)
can be seen as aggregated
by a rule book showing combinations of biops
that should be considered to be
one subprogram call
ie, binding to a particular subprogram;
eg, {?, else} are both biops,
and the rule book would say that
(?, else) is a single function:
?-else(truth,proc,proc).proc
or ?-else(truth,fun,fun).fun .
references for security and speed
7.9: adda/oop/references for security and speed:
. notice how oop would rather
create a new object and modify a pointer
than modify the value of a current object .
. I call this the "(pervasive pointers).
. from an encapsulation view there is no diff',
since only the owning type
can do these mod's .
. what it does seem to uniquely do though,
is encourage the sharing of objects;
ie, if you can modify your value
then I have no interest in sharing its object
because it's no longer synonymous with
the intended value at some past time .
--
. oop is doing for every value
what c does only for arrays .
7.10:
. it does promote strong
capability-based security;
because if everything is through reference,
and ref's are encryptable,
then that is a much stronger encapsulation
unless the system is already protected
by allowing only system-compiled code .
7.11:
. another interesting property of
pervasive pointers
is that by comparing pointers,
one can tell quickly whether
even huge structures are identical;
though if the pointers aren't equal,
they might still represent equal values .
. python has a speed hack where the
first 100 ints have reserved pointers
so in the many loops controlled by small ints,
pointer compares are decisive .
. notice how oop would rather
create a new object and modify a pointer
than modify the value of a current object .
. I call this the "(pervasive pointers).
. from an encapsulation view there is no diff',
since only the owning type
can do these mod's .
. what it does seem to uniquely do though,
is encourage the sharing of objects;
ie, if you can modify your value
then I have no interest in sharing its object
because it's no longer synonymous with
the intended value at some past time .
--
. oop is doing for every value
what c does only for arrays .
7.10:
. it does promote strong
capability-based security;
because if everything is through reference,
and ref's are encryptable,
then that is a much stronger encapsulation
unless the system is already protected
by allowing only system-compiled code .
7.11:
. another interesting property of
pervasive pointers
is that by comparing pointers,
one can tell quickly whether
even huge structures are identical;
though if the pointers aren't equal,
they might still represent equal values .
. python has a speed hack where the
first 100 ints have reserved pointers
so in the many loops controlled by small ints,
pointer compares are decisive .
local resource accesses and wrappers
7.3: adda/portability/local resource accesses and wrappers:
. wondering how adda can provide portable features
and yet also provide access to
individual platform features .
. per each platform,
represent its features as a library,
and then map adda's features to that .
. users can expect portability from
staying with the model;
and can get more into their specific platform
by importing the lib's it offers .
. additionally,
there will never be a portable model of
what paths you can modify;
instead, you have to list per system,
what volumes are available,
and whether they are writable or rom .
7.5:
. adda must include all the storage models,
and must map them to diversely contstrained models:
eg, some platform may offer nothing but a database,
so, adda must provide a hierarchical filesystem
that is implemented by a database .
. wondering how adda can provide portable features
and yet also provide access to
individual platform features .
. per each platform,
represent its features as a library,
and then map adda's features to that .
. users can expect portability from
staying with the model;
and can get more into their specific platform
by importing the lib's it offers .
. additionally,
there will never be a portable model of
what paths you can modify;
instead, you have to list per system,
what volumes are available,
and whether they are writable or rom .
7.5:
. adda must include all the storage models,
and must map them to diversely contstrained models:
eg, some platform may offer nothing but a database,
so, adda must provide a hierarchical filesystem
that is implemented by a database .
Labels:
adda,
architecture,
portability
go's defer statement
7.1: adda/go.lang/defer:
. go.lang has a defer
that is like a type mgt's finalization routine
only it's used by a function
for things that should happen on return .
. ideas I got from that are:
# on return: ... [7.30:
. "(on *condition*) would generally mean
rule-based vs imperative programming;
so (on return: s) would add (s) to
the list of things to do before returning .]
# self`end`+ ... [7.30:
. this is modeled after i`+ 1
which is shorthand for i= i+1 .
. the self is the current subprogram;
it already has an "(end)
listing things to do before ending;
and a (`+) would add to that list .]
. go.lang has a defer
that is like a type mgt's finalization routine
only it's used by a function
for things that should happen on return .
. ideas I got from that are:
# on return: ... [7.30:
. "(on *condition*) would generally mean
rule-based vs imperative programming;
so (on return: s) would add (s) to
the list of things to do before returning .]
# self`end`+ ... [7.30:
. this is modeled after i`+ 1
which is shorthand for i= i+1 .
. the self is the current subprogram;
it already has an "(end)
listing things to do before ending;
and a (`+) would add to that list .]
Ousterhout's dichotomy
7.1: news.adda/Ousterhout's dichotomy:
. John Ousterhout, designer of Tcl,
noticed that high-level programming languages
tend to fall into two groups,
"system programming languages"
and "scripting languages".
[ie you can't have a language that is
optimal for both .
. in defence of that claim,
pypy tried to have a system language Rpython
that was as much as possible like
Python, the scripting lang;
because they wanted
a self-hosting python compiler
ie, one written in python instead of c .
[7.30: like adda,
Rpython is designed to translate into c
for the purpose of avoiding c:
system programmers can use Rpython
yet still take advantage of c compilers .]
. the closest Rpython could get to python
is a subset of it that added static typing;
because, some features that support
coder productivity
are antithetical to features that support
algorithm efficiency .
. Ousterhout was likely pointing out that
scripting lang efficiency was not so important;
because, scripts are glue for
subprograms of sufficient size,
such that most of the run time
is spent in the parts defined by the system lang .
7.30: web:
D. Ancona, M. Ancona, A Cuni, and N. Matsakis.
RPython: a Step Towards Reconciling
Dynamically and Statically Typed OO Languages.
In OOPSLA 2007 Proceedings and Companion, DLS'07:
Proceedings of the 2007 Symposium on
Dynamic Languages, pages 53-64. ACM, 2007(pdf)
. John Ousterhout, designer of Tcl,
noticed that high-level programming languages
tend to fall into two groups,
"system programming languages"
and "scripting languages".
[ie you can't have a language that is
optimal for both .
. in defence of that claim,
pypy tried to have a system language Rpython
that was as much as possible like
Python, the scripting lang;
because they wanted
a self-hosting python compiler
ie, one written in python instead of c .
[7.30: like adda,
Rpython is designed to translate into c
for the purpose of avoiding c:
system programmers can use Rpython
yet still take advantage of c compilers .]
. the closest Rpython could get to python
is a subset of it that added static typing;
because, some features that support
coder productivity
are antithetical to features that support
algorithm efficiency .
. Ousterhout was likely pointing out that
scripting lang efficiency was not so important;
because, scripts are glue for
subprograms of sufficient size,
such that most of the run time
is spent in the parts defined by the system lang .
7.30: web:
D. Ancona, M. Ancona, A Cuni, and N. Matsakis.
RPython: a Step Towards Reconciling
Dynamically and Statically Typed OO Languages.
In OOPSLA 2007 Proceedings and Companion, DLS'07:
Proceedings of the 2007 Symposium on
Dynamic Languages, pages 53-64. ACM, 2007(pdf)
. an approach that attempts to preserve
the flexibility of Python,
while still allowing for efficient execution
is limiting the use of
the more dynamic features of Python
to an initial, bootstrapping phase.
This phase is used to construct
a final RPython (Restricted Python) program
that is actually executed.
RPython is a proper subset of Python,
is statically typed,
and does not allow dynamic modification
of class or method definitions;
however, it can still take advantage of
Python features such as mixins and
first-class methods and classes.
This paper presents an overview of RPython,
including its design and its translation to
both CLI and JVM bytecode.
We show how the bootstrapping phase can be
used to implement advanced features,
like extensible classes and generative programming.
2011-06-30
enum.typed record domains
6.20: adda/dstr/enum.typed record domains:
. in classic lang's like c,
arrays had very different properties
than records .
. in a polymorphic languages however,
records can be more like arrays;
because, although their components vary in type,
the various types often have the same base type;
eg, all types can print their value, etc .
. and any time a record has at least
2 components of the same type,
it could make sense to specify components with
an expression rather than a literal name,
just as is done for arrays .
today's issue is this:
. in trying to unify the concepts of
arrays and records,
there needs to be a way for records to
express their component names as being
some enumeration-type's subrange;
and then, conversely,
any time a record r declares its components' names,
that should induce an enumeration type:
r`domain
-- I'm using the term "(domain) because
arrays and records are like functions;
and, functions in math are known to
input values from a domain type
and output values from a codomain type;
ie, f: domain -> codomain;
or, in adda:
function f(x.domain).codomain,
array A#(domain).codomain
record R.(r1.co1, r2.co2, r3.co3);
R`domain = {r1, r2, r3};
R`codomain = {co1.type, co2.type, co3.type},
. assume there's the enumeration
e.type: {r1, r2, r3};
how should a record say its domain = e ?
R.(r1.co1, r2.co2, r3.co3);
R`domain`= e ?
[6.23: yes,
that lets the record be defined in the usual way,
and then also say that the domain is
not a new declaration,
but rather a reuse of some existing enum.type .]
mis:
. one thing that wouldn't work is this:
R#(e).{co1.type, co2.type, co3.type} ?
-- that would instead be saying
R is an array of enum;
and each var's possible values
are in the set:
{co1.type, co2.type, co3.type}.
--. this could be useful for when
writing programs that write programs:
many of the values they're concerned about
are parts of languages, including types .
. in classic lang's like c,
arrays had very different properties
than records .
. in a polymorphic languages however,
records can be more like arrays;
because, although their components vary in type,
the various types often have the same base type;
eg, all types can print their value, etc .
. and any time a record has at least
2 components of the same type,
it could make sense to specify components with
an expression rather than a literal name,
just as is done for arrays .
today's issue is this:
. in trying to unify the concepts of
arrays and records,
there needs to be a way for records to
express their component names as being
some enumeration-type's subrange;
and then, conversely,
any time a record r declares its components' names,
that should induce an enumeration type:
r`domain
-- I'm using the term "(domain) because
arrays and records are like functions;
and, functions in math are known to
input values from a domain type
and output values from a codomain type;
ie, f: domain -> codomain;
or, in adda:
function f(x.domain).codomain,
array A#(domain).codomain
record R.(r1.co1, r2.co2, r3.co3);
R`domain = {r1, r2, r3};
R`codomain = {co1.type, co2.type, co3.type},
. assume there's the enumeration
e.type: {r1, r2, r3};
how should a record say its domain = e ?
R.(r1.co1, r2.co2, r3.co3);
R`domain`= e ?
[6.23: yes,
that lets the record be defined in the usual way,
and then also say that the domain is
not a new declaration,
but rather a reuse of some existing enum.type .]
mis:
. one thing that wouldn't work is this:
R#(e).{co1.type, co2.type, co3.type} ?
-- that would instead be saying
R is an array of enum;
and each var's possible values
are in the set:
{co1.type, co2.type, co3.type}.
--. this could be useful for when
writing programs that write programs:
many of the values they're concerned about
are parts of languages, including types .
preventing insecure inputs
6.11: adda/abi/insuring security:
[6.13: intro:
. many app's are a security threat because
they are trusted not to smash the stack or heap,
yet will do so if given mal-formed input;
the primary security defense provided by adda
is that all interactions with the stack or heap
are handled by robust system app's .]
. an app may be expecting ascii
and get unicode instead,
but adda typetags would document what was there,
and then the app could take steps to
convert to the prefered type .
[6.24:
. non-native types can have novel structures;
but they are always compositions of
native elemental type;
and, the addx system is helping app's
to read and write the data they exchange .]
[6.13: intro:
. many app's are a security threat because
they are trusted not to smash the stack or heap,
yet will do so if given mal-formed input;
the primary security defense provided by adda
is that all interactions with the stack or heap
are handled by robust system app's .]
. an app may be expecting ascii
and get unicode instead,
but adda typetags would document what was there,
and then the app could take steps to
convert to the prefered type .
[6.24:
. non-native types can have novel structures;
but they are always compositions of
native elemental type;
and, the addx system is helping app's
to read and write the data they exchange .]
oop's multi-dispatch
6.5: adda/oop/multi-dispatch/ working with obj'c:
[6.17: intro:
. according to the wiki,
the term"multi-dispatch refers to
something other than what I assumed it to be
so, I will now explain the diff's .
. everybody agrees on how polymorphism happens
when there is only one argument:
when you write f(x) you mean
x can be any type as long as
x's type defines a function f .
. you don't really know which procedure or method
is being used to define the function f
until you ask x what its type is,
then you use the f-procedure defined by that type .
. that is called dynamic dispatch;
the term "(dispatch) is being used in the same way
as "(taxi dispatcher),
whose decision of which taxi to send
depends on which taxi is free and closest;
likewise, a function call dispatcher
determines which procedure to send the arg to,
and bases its decision on
both the function name,
and the argument's type .
. if the arg is binary,
then a multi-dispatch system has to find
a procedure that is typed for that particular
combination of arg types;
and most such systems use function overloading;
ie, they overload a function's meaning;
eg,
there are many types of cars and motorcycles;
and how a collision turns out
depends on both types;
so then, for each type combination,
you have to define a new procedure
for the car-motorcycle collision function;
that means, for example,
that every time you create a new type of motorcycle,
you have to define as many new collision procedures
as there are types of cars .
. the multi-dispatch system I have in mind
does not use overloading;
rather it expects multiple args to share some supertype;
so, for the cars and motorcycles example,
they could simply share the physics type;
which defines its members as having
a mass and a velocity;
the collision procedure asks both arg's
for their mass and velocity
and then calculates new velocities for each .
. it then sends each arg a message
to change itself to the new velocity,
which each can do with its own version of
a velocitychange(x) procedure .
. that was a simple case because the multi-arg function
could be reduced to a multiple of single-arg functions;
a more complicated case can be found in numerics,
where a binary operation doesn't resolve into
2 unary operations;
. for example, say you had a numeric supertype
that includes only reals and ints;
# it can be overloading the addition function:
+(int, int),
+(real, real)
+(real, int),
+(int, real) .
# or it can use coercion:
it checks to see if types differ,
and then converts one
so both are the same type:
+(int,real) then means a call to
+(real,real);
it then checks whether the destination
is able to accept a real,
or if the destination has a function for
converting a real to its own type .
. now lets say another type, Rational,
is declared to be a subtype of numerics;
this means the supertype procedure for
handling binary operations
has to be updated:
# overloaders then have many more cases to deal with:
{int,real,rational}
x {int,real,rational}.
= 9 cases instead of 4 .
# coercers have another rule to add:
if types differ, then convert ... to ...:
{int,real} to real
{int,rational} to rational
{real, rational} to real .
. in the case of numerics there is a limit to this:
every imaginable subtype of numeric
can be expressed as subtypes of
just these subtypes:
{int, real, rational, complex}
x size-{1,2,4,8byte, huge};
so, for example,
we can declare rainbow to be a subtype of real,
and then the numeric supertype can
-- without ever knowing about rainbows --
see from its type declaration
that it must have a
convert rainbow to real procedure;
and, if a destination is type rainbow,
it again knows from the rainbow declaration
that this destination
has a real assignment procedure .
]-intro
[6.8: 6.17:
. as part of developing for mac,
obj'c features the usual dynamic dispatch .
. the sort of multi-dispatch I have in mind
would fit within mac's type-tagging system;
so for instance,
numerics would have 2 type tags:
# one says it's a subtype of mac's NSobject,
# another is private and indicates
which subtype of numeric it currently is .]
[6.17: intro:
. according to the wiki,
the term"multi-dispatch refers to
something other than what I assumed it to be
so, I will now explain the diff's .
. everybody agrees on how polymorphism happens
when there is only one argument:
when you write f(x) you mean
x can be any type as long as
x's type defines a function f .
. you don't really know which procedure or method
is being used to define the function f
until you ask x what its type is,
then you use the f-procedure defined by that type .
. that is called dynamic dispatch;
the term "(dispatch) is being used in the same way
as "(taxi dispatcher),
whose decision of which taxi to send
depends on which taxi is free and closest;
likewise, a function call dispatcher
determines which procedure to send the arg to,
and bases its decision on
both the function name,
and the argument's type .
. if the arg is binary,
then a multi-dispatch system has to find
a procedure that is typed for that particular
combination of arg types;
and most such systems use function overloading;
ie, they overload a function's meaning;
eg,
there are many types of cars and motorcycles;
and how a collision turns out
depends on both types;
so then, for each type combination,
you have to define a new procedure
for the car-motorcycle collision function;
that means, for example,
that every time you create a new type of motorcycle,
you have to define as many new collision procedures
as there are types of cars .
. the multi-dispatch system I have in mind
does not use overloading;
rather it expects multiple args to share some supertype;
so, for the cars and motorcycles example,
they could simply share the physics type;
which defines its members as having
a mass and a velocity;
the collision procedure asks both arg's
for their mass and velocity
and then calculates new velocities for each .
. it then sends each arg a message
to change itself to the new velocity,
which each can do with its own version of
a velocitychange(x) procedure .
. that was a simple case because the multi-arg function
could be reduced to a multiple of single-arg functions;
a more complicated case can be found in numerics,
where a binary operation doesn't resolve into
2 unary operations;
. for example, say you had a numeric supertype
that includes only reals and ints;
# it can be overloading the addition function:
+(int, int),
+(real, real)
+(real, int),
+(int, real) .
# or it can use coercion:
it checks to see if types differ,
and then converts one
so both are the same type:
+(int,real) then means a call to
+(real,real);
it then checks whether the destination
is able to accept a real,
or if the destination has a function for
converting a real to its own type .
. now lets say another type, Rational,
is declared to be a subtype of numerics;
this means the supertype procedure for
handling binary operations
has to be updated:
# overloaders then have many more cases to deal with:
{int,real,rational}
x {int,real,rational}.
= 9 cases instead of 4 .
# coercers have another rule to add:
if types differ, then convert ... to ...:
{int,real} to real
{int,rational} to rational
{real, rational} to real .
. in the case of numerics there is a limit to this:
every imaginable subtype of numeric
can be expressed as subtypes of
just these subtypes:
{int, real, rational, complex}
x size-{1,2,4,8byte, huge};
so, for example,
we can declare rainbow to be a subtype of real,
and then the numeric supertype can
-- without ever knowing about rainbows --
see from its type declaration
that it must have a
convert rainbow to real procedure;
and, if a destination is type rainbow,
it again knows from the rainbow declaration
that this destination
has a real assignment procedure .
]-intro
[6.8: 6.17:
. as part of developing for mac,
obj'c features the usual dynamic dispatch .
. the sort of multi-dispatch I have in mind
would fit within mac's type-tagging system;
so for instance,
numerics would have 2 type tags:
# one says it's a subtype of mac's NSobject,
# another is private and indicates
which subtype of numeric it currently is .]
Labels:
adda,
multi-dispatch,
oop
alloc'order and size
6.2: adda/mem'mgt/alloc'order and size:
. when using the c lang's dynamic mem'allocator (malloc)
the c`runtime assumes you will be
returning mem in mostly the same order as
when you obtained them .
. if this is not the case,
then there could be heap fragmentation problems .
[6.3:
. use of malloc order may be less complicated
because in modern systems there is v.mem,
so the parts of heap that are
in the way of compacting it
can simply be paged out .]
. the less mem you use at any one time,
the better chance buggy programs around you
don't blow up from exceeding mem limits .
. if needing to alloc mem in a way that could
cause heap fragmentation,
consider how much mem your program is using at once,
and whether you can break it into pieces
that do inout on temp files .
6.17: other strategies:
# at the app level:
. it's easier to find mem even in a fragmented heap
if you're decomposing your mem needs into smaller parts;
eg, instead of alloc'ing 100 contiguous words
for a 10x10 matrix,
you could do 10 alloc's of 10 words each
arranged as an array of pointer to arrays .
# at the os level:
. just as logical files are strings of
many non-contiguous physical mem blocks;
malloc could be impl'ing large mem requests
as strings of smaller mem blocks .
. when using the c lang's dynamic mem'allocator (malloc)
the c`runtime assumes you will be
returning mem in mostly the same order as
when you obtained them .
. if this is not the case,
then there could be heap fragmentation problems .
[6.3:
. use of malloc order may be less complicated
because in modern systems there is v.mem,
so the parts of heap that are
in the way of compacting it
can simply be paged out .]
. the less mem you use at any one time,
the better chance buggy programs around you
don't blow up from exceeding mem limits .
. if needing to alloc mem in a way that could
cause heap fragmentation,
consider how much mem your program is using at once,
and whether you can break it into pieces
that do inout on temp files .
6.17: other strategies:
# at the app level:
. it's easier to find mem even in a fragmented heap
if you're decomposing your mem needs into smaller parts;
eg, instead of alloc'ing 100 contiguous words
for a 10x10 matrix,
you could do 10 alloc's of 10 words each
arranged as an array of pointer to arrays .
# at the os level:
. just as logical files are strings of
many non-contiguous physical mem blocks;
malloc could be impl'ing large mem requests
as strings of smaller mem blocks .
oop storage classes
6.1: adda/type/storage classes:
. recently it was seen how oop's class var's
can be modeled by having vars declared in
the interface type mgt's body
(the implementation module of the interface).
. the same idea can apply to declaring agg' types
(aggregates include the arrays, and records)
which can be just like an interface type
except that an agg's specification can't
declare new operators; [6.20:
ie, the definition of an interface type
is a type that declares
what operations and components
can be applied to obj's of this type;
an agg type is one that need declare only
components .]
. both the {agg', interface} type def's
can declare these 3 storage classes:
# public instance components:
in the typedef's face .
# private instance var's:
in the optional initialization function,
within the typedef's body .
# private class var's:
in the typedef's optional body .
efficiency concerns:
. if the type's face (ada`specification)
doesn't have to declare privates,
then the compiler can never know
what the actual size of an object will be;
whereas, if the face can include
something like: '(privates:0),
then the compiler can potentially know its size .
. however, given the trailer idea
(dynamically extending local mem),
knowing the size is not important anyway:
all act'rec's would have a discriminant bit
indicating the primary record variant:
the one {with, without} a pointer to trailer .
. if with trailer, then any private instance var's
would be on the trailer at that index .
6.1: adda/{begin, end} rename {init,fini}callbacks:
. what I've been calling the {init, fini} routines
should be named {begin, end}
since they mean the same thing in plain english .
. recently it was seen how oop's class var's
can be modeled by having vars declared in
the interface type mgt's body
(the implementation module of the interface).
. the same idea can apply to declaring agg' types
(aggregates include the arrays, and records)
which can be just like an interface type
except that an agg's specification can't
declare new operators; [6.20:
ie, the definition of an interface type
is a type that declares
what operations and components
can be applied to obj's of this type;
an agg type is one that need declare only
components .]
. both the {agg', interface} type def's
can declare these 3 storage classes:
# public instance components:
in the typedef's face .
# private instance var's:
in the optional initialization function,
within the typedef's body .
# private class var's:
in the typedef's optional body .
efficiency concerns:
. if the type's face (ada`specification)
doesn't have to declare privates,
then the compiler can never know
what the actual size of an object will be;
whereas, if the face can include
something like: '(privates:0),
then the compiler can potentially know its size .
. however, given the trailer idea
(dynamically extending local mem),
knowing the size is not important anyway:
all act'rec's would have a discriminant bit
indicating the primary record variant:
the one {with, without} a pointer to trailer .
. if with trailer, then any private instance var's
would be on the trailer at that index .
6.1: adda/{begin, end} rename {init,fini}callbacks:
. what I've been calling the {init, fini} routines
should be named {begin, end}
since they mean the same thing in plain english .
2011-06-28
a brief history of compound documents
5.7: web.adde/compound doc/problems:
. the compound doc is a really simple idea;
it works just like the way that your mac's gui
displays a window of various apps,
except that window arrangments can be
saved as documents, and windows can be borderless
as if they are part of the same document .
. but from reading opendoc's history
you'd think it was a plague .
"(. compound documents are said to be
an oversold concept:
there just aren't that many examples
beyond mixing graphics with text .)
--
. tell that to the html`object tag:
we routinely see combinations of
movies, photo's, text, script images,
and anything you have an app for .
. something about the plague again:
other compound doc specifications
had the same problem!
. the specification should have included
a manifest that listed what app's you need
in order to open a given document .
more compound doc' technology is history:
OLE, OLE Automation, ActiveX, COM+ and DCOM .
[ com is oop++ ]
COM's architect"Anthony Williams:
so, COM must additionally specify:
. the compound doc is a really simple idea;
it works just like the way that your mac's gui
displays a window of various apps,
except that window arrangments can be
saved as documents, and windows can be borderless
as if they are part of the same document .
. but from reading opendoc's history
you'd think it was a plague .
"(. compound documents are said to be
an oversold concept:
there just aren't that many examples
beyond mixing graphics with text .)
--
. tell that to the html`object tag:
we routinely see combinations of
movies, photo's, text, script images,
and anything you have an app for .
. an amazingly bad specification or implementation--
was opendoc's biggest problem:
it was very common to find
apps that could not even
open a document created by another app .
. OpenDoc attempted to solve this problem by
allowing developers to store multiple formats
to represent the same document object.
For instance, it was both possible and encouraged
to store a common format like JPEG
along with an editable binary format,
but in practice few developers
followed this recommendation.
. something about the plague again:
other compound doc specifications
had the same problem!
. the specification should have included
a manifest that listed what app's you need
in order to open a given document .
more compound doc' technology is history:
Dynamic Data Exchange (DDE, 1987),. ms`COM is often an umbrella term for
allowed "conversations" between applications.
OLE(1991, (Object Linking and Embedding).)
was Microsoft's first object-based framework,
and MS`Office's first compound doc' technology;
it was built on top of DDE .
. While OLE 1 was focused on compound documents,
COM and OLE 2 (1992-93) were designed to address
software components (oop++) in general.
. OLE custom controls (OCXs, 1994)
. Internet is a new use for
OLE Custom Controls (ActiveX, 1996),
-- gradually renamed all OLE technologies to ActiveX,
except the compound document technology
that was used in Microsoft Office.
DCOM (Distributed COM, 1996)
competed with CORBA as the model for
code and service-reuse over the Internet.
difficulties getting either of these
over Internet firewalls .
MTS run-time increased scalability, robustness,
and simplified system management.
OLE, OLE Automation, ActiveX, COM+ and DCOM .
[ com is oop++ ]
COM's architect"Anthony Williams:
Object ArchitectureCharlie Kindel 1997:
is concerned with Dealing With the Unknown
and ensuring Type Safety in a
Dynamically Extensible Class Library;
also significant to com
was clarifying what oop`Inheritance is,
and knowing How To Use It .
(popular) oop =C++ supports only oop not cop
Polymorphism + (Some) Late Binding
+ (Some) Encapsulation
+ Inheritance
Component Oriented Programming (cop) =
Polymorphism + (Really) Late Binding
+ (Real, Enforced) Encapsulation
+ Interface Inheritance
+ Binary Reuse” .
so, COM must additionally specify:
* Execution environment options
(so-called Apartments)
* Inter-process Marshalling
* Remote Object Activation mechanism and protocols
* Threading models
. the C++ linkage model impedescom provides what c++ is missing:
binary distribution and reuse .
. by using shared object linking,
the lack of binary standardisation
means there is an interoperability problem .
C++ lacks binary encapsulation:
ie, while it supports separation of
interface and implementation,
it's only at the syntax level
– not at the binary level.
implementation changes are “seen” by clients.
A “substrate” for building re-usable components.
. Interfaces are defined in COM IDL
(IDL + COM extensions for inheritance and polymorphism)
OS Neutral and (nearly) Language neutral:
. can be used from any language that can
generate/grok vtbl’s and vptrs.
. a packed bit field is returned
with every COM access .
categories define
an implementation of a given interface
that meets some set of constraints .
Labels:
ABI,
adde,
compound doc's
cross-platform task mgt survey
5.4: adde/universal view of task mgt:
. compare the various ways provided by
{mac, pc, linux} to see what's running:
# mac:
. a dock contains your favorite and active apps;
the dock marks currently active apps;
so, it might be called an app.bar .
. the [all windows].key shows all windows
in a non-overlapping arrangement;
the [current app's windows].key shows a similar
non-overlapping arrangement of
just those windows owned by the current app .
. mission control combines the
[all windows].key with the
[current app's windows]`function
by not only showing all windows in a
non-overlapping arrangement
but also grouping windows together
according to which app they're owned by .
# pc, linux:
. a taskbar has icons for each window;
press an icon to bring its window to the front .
# pc (group similar taskbar buttons):
. the taskbar has an icon for each app
and the effect of pressing on one
depends on how many windows that app has open:
if just 1 window, it brings that window to the front;
for many windows,
it shows a menu of that app's current windows;
the user selects one, and that window comes forward .
tabbing:
. all systems use the tab key for
(with ctrl or command) to select a window .
# mac:
show what's active in the dock;
# pc, linux:
list what's in the taskbar .
projectbar:
. usually there's been one desktop
containing all your windows;
if there were more than one desktop
then they could each hold
project-specific windows .
. for this I coined the term projectbar
to match how taskbar is literally
a bar of tasks .
. mac's name for projectbar is Spaces,
and its Dashboard involves the same idea .
. Dashboard uses a key for popping up
a 2nd desktop whose project is
the use of widgets
which are lightweight utilities
like calculators and clocks,
or data displays like weather,
calender, and ticker tape .
. another use of the Dashboard Space
could be task mgt;
where both {dock, taskbar}
are kept on the 2nd desktop .
. compare the various ways provided by
{mac, pc, linux} to see what's running:
# mac:
. a dock contains your favorite and active apps;
the dock marks currently active apps;
so, it might be called an app.bar .
. the [all windows].key shows all windows
in a non-overlapping arrangement;
the [current app's windows].key shows a similar
non-overlapping arrangement of
just those windows owned by the current app .
. mission control combines the
[all windows].key with the
[current app's windows]`function
by not only showing all windows in a
non-overlapping arrangement
but also grouping windows together
according to which app they're owned by .
# pc, linux:
. a taskbar has icons for each window;
press an icon to bring its window to the front .
# pc (group similar taskbar buttons):
. the taskbar has an icon for each app
and the effect of pressing on one
depends on how many windows that app has open:
if just 1 window, it brings that window to the front;
for many windows,
it shows a menu of that app's current windows;
the user selects one, and that window comes forward .
tabbing:
. all systems use the tab key for
(with ctrl or command) to select a window .
# mac:
show what's active in the dock;
# pc, linux:
list what's in the taskbar .
projectbar:
. usually there's been one desktop
containing all your windows;
if there were more than one desktop
then they could each hold
project-specific windows .
. for this I coined the term projectbar
to match how taskbar is literally
a bar of tasks .
. mac's name for projectbar is Spaces,
and its Dashboard involves the same idea .
. Dashboard uses a key for popping up
a 2nd desktop whose project is
the use of widgets
which are lightweight utilities
like calculators and clocks,
or data displays like weather,
calender, and ticker tape .
. another use of the Dashboard Space
could be task mgt;
where both {dock, taskbar}
are kept on the 2nd desktop .
documents as folder trees
5.11: adde/documents as folder trees:
[4.21:
. just as trees of folders can be merged,
the same should apply to documents as well,
with each subtitle being like a subfolder .]
. that introduces a 3rd dimension of merging
(volume, folder path, file);
and,
many merge styles:
# mac style:
. don't merge anything .
# pc style:
. merge folders, replace files .
# versioned merge:
. merge folders and avoid replacing files
by renaming them instead
with appended version numbers .
. the versions numbers rotate through 0...n;
so eventually data is lost .
# subfile merge:
. merge folders and files;
paragraphs are combined rather than replaced
(default is new subsections are appended
to older subsections).
# journaled merge:
. this is like the subfile merge (above)
except that there are instructions such as
delete the nth paragraph of a subsection;
or run a patch over it .
[4.21:
. the journal's files would pay attention to
subtitle pathname
and only then consider character position .
. this is in contrast to the typical
{revision, version}* control system
which measure all changes in terms of
character position .]
--
. intra-document structuring is
necessarily language-specific,
except at the level of characters,
whereas the unix way is tool reuse,
and so the patch tool must be
language-agnostic .
*:
revisions vs versions (terminology proposal):
# revisions are corrections or
efficiency enhancements;
# versions are parameterized configurations
for adapting to various situations
or new design ideas .
[4.21:
. just as trees of folders can be merged,
the same should apply to documents as well,
with each subtitle being like a subfolder .]
. that introduces a 3rd dimension of merging
(volume, folder path, file);
and,
many merge styles:
# mac style:
. don't merge anything .
# pc style:
. merge folders, replace files .
# versioned merge:
. merge folders and avoid replacing files
by renaming them instead
with appended version numbers .
. the versions numbers rotate through 0...n;
so eventually data is lost .
# subfile merge:
. merge folders and files;
paragraphs are combined rather than replaced
(default is new subsections are appended
to older subsections).
# journaled merge:
. this is like the subfile merge (above)
except that there are instructions such as
delete the nth paragraph of a subsection;
or run a patch over it .
[4.21:
. the journal's files would pay attention to
subtitle pathname
and only then consider character position .
. this is in contrast to the typical
{revision, version}* control system
which measure all changes in terms of
character position .]
--
. intra-document structuring is
necessarily language-specific,
except at the level of characters,
whereas the unix way is tool reuse,
and so the patch tool must be
language-agnostic .
*:
revisions vs versions (terminology proposal):
# revisions are corrections or
efficiency enhancements;
# versions are parameterized configurations
for adapting to various situations
or new design ideas .
Labels:
adde,
journaled fs,
subfiles
avoiding freezes with real concurrency
5.21: 6.2: adda/translate/co
there were 2 cases of multi-tasking:
# gui reactor:
. the multi-tasking done for gui response
could really be done by
frequent subroutine calls to the gui handler
instead of swapping threads with it;
because, its endless event loop is equivent to
an endless number of brief loop body calls .
# time-slicing:
. when a program is composed of threads (co.programs),
it expects them to be time-sliced,
so that, for instance,
if there are several things to animate,
each refresh of the screen is showing
what appears to be concurrent activity .
. unlike the gui-reactor case,
there is no way to use a subroutine call for
sharing cpu time with anonymous threads;
because, generally they cannot be decomposed into
an endless number of brief loop body calls .
. a similar case is anonymous co.programming,
where the user runs several programs at once;
this situation is significantly unlike
app-orchestrated co.programming because
user-launched co.programs aren't aware of each other;
so, even if c did support coroutines,
they would not be of use in time-slicing here .
5.22:
. another place where programs can hang
besides infinite looping and recursion,
is waiting for devices to respond;
the addx library designer needs to know
where these hangups are,
and not give tasks direct access to them .
. instead,
the sub is suspended until the wait is over;
and control is given instead to gui reactions .
[6.2:
. it may be the case that
only hardware-based concurrency could provide
the needed protection from device freezes;
that means the base language can't be just c,
but involve c+posix, obj-c + gcd, or qt .]
5.29: web.adda/translate/co/open concurrency api's:
. unix is a std open platform now,
isn't there some concurrency api defined in posix?
. an overview of user-level vs kernel-level
and threads vs processes:
. processes communicate via sockets
pos:
. addx's primary use for threads is that
the main thread is adde dishing up the gui,
and it sends messages to a side thread
for housing the apps that do the actual work .
. while getting bogged down in posix idioms
it occured to me that since my first target is mac,
I should follow what they suggest
in the way of concurrency primitives .
...
there's also qt:
both open, cross-platform and easier than posix .
there were 2 cases of multi-tasking:
# gui reactor:
. the multi-tasking done for gui response
could really be done by
frequent subroutine calls to the gui handler
instead of swapping threads with it;
because, its endless event loop is equivent to
an endless number of brief loop body calls .
# time-slicing:
. when a program is composed of threads (co.programs),
it expects them to be time-sliced,
so that, for instance,
if there are several things to animate,
each refresh of the screen is showing
what appears to be concurrent activity .
. unlike the gui-reactor case,
there is no way to use a subroutine call for
sharing cpu time with anonymous threads;
because, generally they cannot be decomposed into
an endless number of brief loop body calls .
. a similar case is anonymous co.programming,
where the user runs several programs at once;
this situation is significantly unlike
app-orchestrated co.programming because
user-launched co.programs aren't aware of each other;
so, even if c did support coroutines,
they would not be of use in time-slicing here .
5.22:
. another place where programs can hang
besides infinite looping and recursion,
is waiting for devices to respond;
the addx library designer needs to know
where these hangups are,
and not give tasks direct access to them .
. instead,
the sub is suspended until the wait is over;
and control is given instead to gui reactions .
[6.2:
. it may be the case that
only hardware-based concurrency could provide
the needed protection from device freezes;
that means the base language can't be just c,
but involve c+posix, obj-c + gcd, or qt .]
5.29: web.adda/translate/co/open concurrency api's:
. unix is a std open platform now,
isn't there some concurrency api defined in posix?
. an overview of user-level vs kernel-level
and threads vs processes:
. processes communicate via sockets
pos:
. addx's primary use for threads is that
the main thread is adde dishing up the gui,
and it sends messages to a side thread
for housing the apps that do the actual work .
. while getting bogged down in posix idioms
it occured to me that since my first target is mac,
I should follow what they suggest
in the way of concurrency primitives .
...
there's also qt:
both open, cross-platform and easier than posix .
Labels:
adda,
concurrency,
translation
classification by superset decomposition
5.15: adda/oop/type cluster/
templates for subtype association:
[6.1: mis:
irrationals are simply the reason
why some reals are not Q's !
. what is the purpose of knowing how they are related?
isn't it just to know type compatibility?
if you produce an irrational,
you call it a real,
and if you didn't want symbolics
then you'd call it a float .]
. the mgt for type clusters(eg numbers),
may have some reusable code in that there are
many type clusters in which the subtypes have
values that are subsets of each other; eg,
N subsets Z subsets Q subsets R subsets C .
. number is also an example of there being
another way of describing subsets:
superset decomposition
(showing how a set is composed of other sets).
. saying which subset relations exist
doesn't neatly show the relation of irrationals
(ones not expressible as a ratio, and
having an infinite and non-recurring expansion
when expressed as a decimal).
N = 0.. infinity;
Z= {+1,-1}*N;
Q = {Z/N, Z};
irrationals = {pi, e, 2**(1/2), ...}:
pi/4 = +(^i=0...infinity| (-1)**i /(2i+1) )
pi/2 = *(^i=1...infinity| (2i)**2 /(2i)**2-1) )
pi = 4 / (1+ 1**2 /( 3+ 2**2 /(5+ 3**2 /(...)))
e = (1+1/infinity)**infinity .
R = {Q, irrationals, repeaters}
C = {i*R + R, R} -- i = (-1)**(1/2)
templates for subtype association:
[6.1: mis:
"( . having types specifying which subset relations exist)??
doesn't neatly show the relation of irrationals
irrationals are simply the reason
why some reals are not Q's !
. what is the purpose of knowing how they are related?
isn't it just to know type compatibility?
if you produce an irrational,
you call it a real,
and if you didn't want symbolics
then you'd call it a float .]
. the mgt for type clusters(eg numbers),
may have some reusable code in that there are
many type clusters in which the subtypes have
values that are subsets of each other; eg,
N subsets Z subsets Q subsets R subsets C .
. number is also an example of there being
another way of describing subsets:
superset decomposition
(showing how a set is composed of other sets).
. saying which subset relations exist
doesn't neatly show the relation of irrationals
(ones not expressible as a ratio, and
having an infinite and non-recurring expansion
when expressed as a decimal).
N = 0.. infinity;
Z= {+1,-1}*N;
Q = {Z/N, Z};
irrationals = {pi, e, 2**(1/2), ...}:
pi/4 = +(^i=0...infinity| (-1)**i /(2i+1) )
pi/2 = *(^i=1...infinity| (2i)**2 /(2i)**2-1) )
pi = 4 / (1+ 1**2 /( 3+ 2**2 /(5+ 3**2 /(...)))
e = (1+1/infinity)**infinity .
R = {Q, irrationals, repeaters}
C = {i*R + R, R} -- i = (-1)**(1/2)
Labels:
adda,
oop,
type cluster
1st-class functions and various environs
adda/oop/1st-class functions:
5.16:
. a function's owner is the environs in which
the function's body is defined; [6.1:
a top-level subprogram is owned by the library,
and thereby has access to the standard lib' .]
. most functions are owned by types:
the type's body provides the environs;
but 1st-class function support means that
an aggregate's components may be a function,
in which case, the agg is the owner,
so the agg's body and its other components
become the function's environs .
[5.18: clarification:
. agg's can have bodies like Ada packages;
and if the agg' body contains the function body
only then does the agg' own the function .
5.31: 6.28:
. the agg'component can also be
a pointer to an external function;
such a function then has no way to reach
agg' components;
conversely, Ada's stub declaration allows for
an agg'owned function to be defined externally;
it's still declared locally if not defined so,
and declaration is what gives it local access,
and a locality to call its own .]
[5.17:
. an agg's components can be addressed in 2 ways:
# directly:
. a function it owns knows what's available
and reaches an external x with (../x) .
# a filesystem approach:
. the function can get a list of
the names of surrounding components,
just as a human asks a filesystem
for a directory listing .
--
. a function's use of (self`name) could return
the name of the component it's been assigned to ... 6.1:
. it could be assigned to more than
one component of its owner;
so, that would have to be a list .]
5.31: deleting self:
. can a function delete itself from a agg'?
it can reach and modify other components
from within the agg' it's a component of;
so why not be able to delete itself?
it could still run after such a deletion
because it's an active process
and each act'rec on the stack display
is paired with a pointer to the associated code . [6.1:
. one reason for deleting self could be
a varying method pattern:
it calls multiple agg'components,
some of which may be self,
and changes methods to meet new conditions .]
5.17: all accesses must be cap'based:
[5.16:
. how would an external function
ask for access to the class var's?
. it can't use ../ because it's
local to an instance, whereas
class var's are local to the type's body .
. it could work like a filesystem,
where functions can request a list
of their owner's class var's .
. the type's body allows access by
populating the class's locals list
with the addresses it wishes to share
rather than leaving the list null ...]
...
. the idea of assignable functions
having access to class var's
must be integrated with a security model
that considers who's asking for the access
and who's affected by it .
. it's not just a matter of selecting
which locals are visible,
but also deciding which functions
can have that access:
the filtering might be by function-type,
function-authors, or function-libraries .
5.18: dimensions of environs:
. a function.ptr assigned to an agg' component
is just like when passed to a subprogram param;
in either of these cases,
a function body's own environ
is not the same as caller's body .
. there can also be structural environs
(what agg'path was used for accessing
a copy of the function's address).
. when a call is made, the function gets a
return address that is a shortcut to
this scope path:
main/sub/nth step/m-th step of sub.body(eg, a loop) .
. that leads to the call's location
which includes the data path needed to
access the function: [6.28: ...
by looking on the stack's return address,
and then looking at the code
that launched that function call,
we are finding the structural environs .]
. some variants of lisp
feature dynamic scope
in which a called function can expect access to
the caller's environ's .
. is there any language that provides
access to the structural environs?
. lisp functions can also know
who their caller is,
and what their caller's code is .
. it seems like the
full generalization of that would be
pointers to all related structures:
the owner, the caller,
the call or return point,
and the path of caller's access to function .
. practically though,
the simple and safe way is
accessing only what's available at compile time .
. if the function wants to share the caller's locals,
it can declare an inout param
that callers need to fill;
if the caller wants a function to share,
it can take ownership of the function .
5.16:
. a function's owner is the environs in which
the function's body is defined; [6.1:
a top-level subprogram is owned by the library,
and thereby has access to the standard lib' .]
. most functions are owned by types:
the type's body provides the environs;
but 1st-class function support means that
an aggregate's components may be a function,
in which case, the agg is the owner,
so the agg's body and its other components
become the function's environs .
[5.18: clarification:
. agg's can have bodies like Ada packages;
and if the agg' body contains the function body
only then does the agg' own the function .
5.31: 6.28:
. the agg'component can also be
a pointer to an external function;
such a function then has no way to reach
agg' components;
conversely, Ada's stub declaration allows for
an agg'owned function to be defined externally;
it's still declared locally if not defined so,
and declaration is what gives it local access,
and a locality to call its own .]
[5.17:
. an agg's components can be addressed in 2 ways:
# directly:
. a function it owns knows what's available
and reaches an external x with (../x) .
# a filesystem approach:
. the function can get a list of
the names of surrounding components,
just as a human asks a filesystem
for a directory listing .
--
. a function's use of (self`name) could return
the name of the component it's been assigned to ... 6.1:
. it could be assigned to more than
one component of its owner;
so, that would have to be a list .]
5.31: deleting self:
. can a function delete itself from a agg'?
it can reach and modify other components
from within the agg' it's a component of;
so why not be able to delete itself?
it could still run after such a deletion
because it's an active process
and each act'rec on the stack display
is paired with a pointer to the associated code . [6.1:
. one reason for deleting self could be
a varying method pattern:
it calls multiple agg'components,
some of which may be self,
and changes methods to meet new conditions .]
5.17: all accesses must be cap'based:
[5.16:
. how would an external function
ask for access to the class var's?
. it can't use ../ because it's
local to an instance, whereas
class var's are local to the type's body .
. it could work like a filesystem,
where functions can request a list
of their owner's class var's .
. the type's body allows access by
populating the class's locals list
with the addresses it wishes to share
rather than leaving the list null ...]
...
. the idea of assignable functions
having access to class var's
must be integrated with a security model
that considers who's asking for the access
and who's affected by it .
. it's not just a matter of selecting
which locals are visible,
but also deciding which functions
can have that access:
the filtering might be by function-type,
function-authors, or function-libraries .
5.18: dimensions of environs:
. a function.ptr assigned to an agg' component
is just like when passed to a subprogram param;
in either of these cases,
a function body's own environ
is not the same as caller's body .
. there can also be structural environs
(what agg'path was used for accessing
a copy of the function's address).
. when a call is made, the function gets a
return address that is a shortcut to
this scope path:
main/sub/nth step/m-th step of sub.body(eg, a loop) .
. that leads to the call's location
which includes the data path needed to
access the function: [6.28: ...
by looking on the stack's return address,
and then looking at the code
that launched that function call,
we are finding the structural environs .]
. some variants of lisp
feature dynamic scope
in which a called function can expect access to
the caller's environ's .
. is there any language that provides
access to the structural environs?
. lisp functions can also know
who their caller is,
and what their caller's code is .
. it seems like the
full generalization of that would be
pointers to all related structures:
the owner, the caller,
the call or return point,
and the path of caller's access to function .
. practically though,
the simple and safe way is
accessing only what's available at compile time .
. if the function wants to share the caller's locals,
it can declare an inout param
that callers need to fill;
if the caller wants a function to share,
it can take ownership of the function .
Labels:
1st-class functions,
adda,
oop
adopting oop features`round#1
5.16: adda/oop/integrating popular oop features:
. for each oop feature,
adda has to show how it's done,
or explain why it shouldn't be done
(eg, insecure, ill-fitting, ...);
eg, for oop's version of f(x), x`f,
how is adda providing f with access to x ?
where various oop styles differ:
. popular oop assumes the use of references:
all obj's are a ptr to a disposable heap obj;
whereas, adda assumes direct access to value,
ie, there's nothing to explicitely dispose of;
and when an assignment is made,
it happens to the value not a pointer .
[6.1:
. no garbage is generated because
any function that returns an object
does so through an inout parameter
in which it receives from the caller
the memory where the result will go .
]
. there are 4 modules used by oop:
a type-mgt or class object
and an instance object,
each with a {const, var} section; [6.28:
--
anything known to be constant is sharable;
it can be part of subprogram's code template
instead of the subprogram activation record .]
. functions of the form y = obj`f(x)
are actually calling a procedure:
f(input x,
inout obj,
inout y) )
thereby giving the function 2 implicit parameters,
represented in the method as the var's: y, and o:
# y,
as in y = f(x);
. y represents the address where
the return is being placed by f's caller .
. the function then gets to reuse y's mem .
# o,
as in o`f(x);
o is an object whose type defines f,
and f has access to all of o's internals .
adda's class vars:
. the type's body is where methods are defined;
this space can also declare variables
which are then sharable by all methods,
addressed in the usual unix way:
../local . [5.31:
. these var's are initialized at program startup,
like those in an ada package body .]
where is a local function's return directed?:
[6.1: intro:
. oop's y = x`f means f can both modify x,
and return things to y .
. a local function here means
local to an aggregate (an agg'owned function)
where (y= x.f) or (y= x#f)
can modify components of x, including itself,
and then return something to y .]
. the local function's return
can be assumed to target y because
if it wanted to operate on its owner,
it would simply use ../ to access those parts; [5.16: 5.17:
eg,
b`= obj.f -- here, obj is an aggregate;
and, one of its components is named f,
which is a function with an implicit arg of
potentially all of obj's other components;
finally,
f is in control of what gets assigned to (b);
because f determines what (obj.f) eval's to;
ie, obj itself is not what (b) is being assigned;
obj is merely the source of the function
which then provides the assignment's content .]
[5.31:
. the same reasoning applies to the usual
type-owned functions, y`= x`f,
they have the option of returning either the object
or something entirely different;
eg, x`++ -- this increments x,
but then returns x's former value .]
. the x`f form simply means that f has
inout access to x .[6.1:
(in the context of inheritance,
f is a abstract function whose method is determined by
the type that x belongs to,
but this feature is not specific to the x`f form,
it also applies to f(x)
-- it even applies to a+b because
both {a, b} share a common supertype
that knows how to mix its subtypes) .]
5.18: composite messages:
. obj'c allows for the composition of message-sends;
eg, x`= [a g b]; [x f y]
can be composed as [[a g b] f y]
because sending a msg to an obj typically results in
an obj pointer being returned;
ie, [x g b] points at x;
so, how does adda do that?
x`g(b)`f(y) could work the same as obj'c's
[[x g b] f y] . [5.31:
. why wouldn't the parse be
x`( g(b)`f(y) ) instead of
( x`g(b) )`f(y) ?
can the (f) in (x`f) be a variable instead a literal ?
(f x) can be expressed as (v`=x; f@v);
likewise, (x`f) could be (@x`@v) ?
. the purpose of (x`f) was to emulate
c's x++, and oop's x.f;
in those cases only literals are needed,
but obj'c has a call for variable msg's too .
. a neater way than x`@v
would be simply x`v,
where v had been declared to be a pointer to symbol .
. or use explicit parentheses:
(expression returns pointer to obj)`(
expression returns pointer to method symbol) .
6.1:
. while features should be complete
to the point of orthogonal,
this should not be at expense of
unintuitive syntax;
esp'ly for features that are used infrequently .]
. for each oop feature,
adda has to show how it's done,
or explain why it shouldn't be done
(eg, insecure, ill-fitting, ...);
eg, for oop's version of f(x), x`f,
how is adda providing f with access to x ?
where various oop styles differ:
. popular oop assumes the use of references:
all obj's are a ptr to a disposable heap obj;
whereas, adda assumes direct access to value,
ie, there's nothing to explicitely dispose of;
and when an assignment is made,
it happens to the value not a pointer .
[6.1:
. no garbage is generated because
any function that returns an object
does so through an inout parameter
in which it receives from the caller
the memory where the result will go .
]
. there are 4 modules used by oop:
a type-mgt or class object
and an instance object,
each with a {const, var} section; [6.28:
--
anything known to be constant is sharable;
it can be part of subprogram's code template
instead of the subprogram activation record .]
. functions of the form y = obj`f(x)
are actually calling a procedure:
f(input x,
inout obj,
inout y) )
thereby giving the function 2 implicit parameters,
represented in the method as the var's: y, and o:
# y,
as in y = f(x);
. y represents the address where
the return is being placed by f's caller .
. the function then gets to reuse y's mem .
# o,
as in o`f(x);
o is an object whose type defines f,
and f has access to all of o's internals .
adda's class vars:
. the type's body is where methods are defined;
this space can also declare variables
which are then sharable by all methods,
addressed in the usual unix way:
../local . [5.31:
. these var's are initialized at program startup,
like those in an ada package body .]
where is a local function's return directed?:
[6.1: intro:
. oop's y = x`f means f can both modify x,
and return things to y .
. a local function here means
local to an aggregate (an agg'owned function)
where (y= x.f) or (y= x#f)
can modify components of x, including itself,
and then return something to y .]
. the local function's return
can be assumed to target y because
if it wanted to operate on its owner,
it would simply use ../ to access those parts; [5.16: 5.17:
eg,
b`= obj.f -- here, obj is an aggregate;
and, one of its components is named f,
which is a function with an implicit arg of
potentially all of obj's other components;
finally,
f is in control of what gets assigned to (b);
because f determines what (obj.f) eval's to;
ie, obj itself is not what (b) is being assigned;
obj is merely the source of the function
which then provides the assignment's content .]
[5.31:
. the same reasoning applies to the usual
type-owned functions, y`= x`f,
they have the option of returning either the object
or something entirely different;
eg, x`++ -- this increments x,
but then returns x's former value .]
. the x`f form simply means that f has
inout access to x .[6.1:
(in the context of inheritance,
f is a abstract function whose method is determined by
the type that x belongs to,
but this feature is not specific to the x`f form,
it also applies to f(x)
-- it even applies to a+b because
both {a, b} share a common supertype
that knows how to mix its subtypes) .]
5.18: composite messages:
. obj'c allows for the composition of message-sends;
eg, x`= [a g b]; [x f y]
can be composed as [[a g b] f y]
because sending a msg to an obj typically results in
an obj pointer being returned;
ie, [x g b] points at x;
so, how does adda do that?
x`g(b)`f(y) could work the same as obj'c's
[[x g b] f y] . [5.31:
. why wouldn't the parse be
x`( g(b)`f(y) ) instead of
( x`g(b) )`f(y) ?
can the (f) in (x`f) be a variable instead a literal ?
(f x) can be expressed as (v`=x; f@v);
likewise, (x`f) could be (@x`@v) ?
. the purpose of (x`f) was to emulate
c's x++, and oop's x.f;
in those cases only literals are needed,
but obj'c has a call for variable msg's too .
. a neater way than x`@v
would be simply x`v,
where v had been declared to be a pointer to symbol .
. or use explicit parentheses:
(expression returns pointer to obj)`(
expression returns pointer to method symbol) .
6.1:
. while features should be complete
to the point of orthogonal,
this should not be at expense of
unintuitive syntax;
esp'ly for features that are used infrequently .]
Subscribe to:
Posts (Atom)
