Hello Stephen,
first of all, thank you for sharing some insight about Aldor.
I love the approach that domain-constructing functions are _not_ treated
special, but the speciality is hidden in the context.
Awesome!
Although this can be found in the Aldor User Guide, I could not find it
before reading your mail.
You now have changed my perspective on Aldor a bit, and I love that even
more.
It explains an aspect of Aldor, that has been quite fuzzy for me before.
However, domain-constructing functions may also occur in non-Type context.
There the domain-constructing function is called again and again. Consider
the following piece of code:
#include "aldor"
import from Integer;
import from MachineInteger;
import from TextWriter, String, Character;
Dom( param: Integer ): with {
f: () -> Integer
} == {
import from RandomNumberGenerator;
local r: Integer := randomInteger() :: Integer;
stdout << "Domain ( param : " << ( param ) << ") -- r: " << r <<
newline;
add {
--f yields a domain's r
f(): Integer == { r }
}
}
macro NUM == ( max::Integer quo 2 );
stdout << "call : " << f()$Dom( next NUM ) << newline;
stdout << "call : " << f()$Dom( next NUM ) << newline;
local t1: Type := Dom( next NUM );
local t2: Type := Dom( next NUM );
local t3: Type := Dom( next NUM );
The Dom(...) at the 2 "stdout" lines is in type context. So these line are
responsible for one instantiation of Dom. However, the Dom for t1, t2, and
t3 are not in type context. Therefore, The domain constructing function
Dom is actually called.
To verify my claims, let me give you the output:
Domain ( param : 1073741824) -- r: 2039368176
call : 2039368176
call : 2039368176
Domain ( param : 1073741824) -- r: 881855875
Domain ( param : 1073741824) -- r: 1363117465
Domain ( param : 1073741824) -- r: 11671655
This kind of writing code may lead to incompatible types (well... simply
by non functional behaviour of domain-constructing functions), as can be
seen in this example:
#include "aldor"
import from Integer;
import from MachineInteger;
import from TextWriter, String, Character;
Dom(): with {
coerce: Integer -> %;
coerce: % -> Integer;
(+): ( %, % ) -> %;
} == add {
Rep == Integer;
coerce( a : Integer ): % == { per a };
coerce( a : % ): Integer == { rep a };
(+)( a : %, b : % ): % == { per( rep a + rep b ) };
}
macro NUM == ( max::Integer quo 2 );
T0 == Dom();
T1 == Dom();
local t2: Type := Dom();
T2 == t2;
import from T0, T1, T2;
--T0 and T1 refer to the same domain.
stdout << "( T0 + T0 ) -> T0 : " << (coerce$T0)( (coerce$T0)( 1 )
+ (coerce$T0)( 1 ) ) << newline;
stdout << "( T1 + T0 ) -> T0 : " << (coerce$T0)( (coerce$T1)( 1 )
+ (coerce$T0)( 1 ) ) << newline;
stdout << "( T1 + T0 ) -> T1 : " << (coerce$T1)( (coerce$T1)( 1 )
+ (coerce$T0)( 1 ) ) << newline;
stdout << "( T1 + T1 ) -> T0 : " << (coerce$T0)( (coerce$T1)( 1 )
+ (coerce$T1)( 1 ) ) << newline;
The output of the example is
( T0 + T0 ) -> T0 : 2
( T1 + T0 ) -> T0 : 2
( T1 + T0 ) -> T1 : 2
( T1 + T1 ) -> T0 : 2
However, T2 does not refer to T0 or T1, as adding the line
stdout << "( T2 + T0 ) -> T0 : " << (coerce$T0)( (coerce$T2)( 1 )
+ (coerce$T0)( 1 ) ) << newline;
shows by yielding
"test2.as", line 32:
stdout << "( T2 + T0 ) -> T0 : " << (coerce$T0)( (coerce$T2)( 1 )
+ (coerce$T0)( 1 ) ) << newline;
.........................................................^
[L32 C58] #1 (Error) There are no suitable meanings for the operator
`coerce$T2'.
at compilation time.
Did this happen by intention, or does the language provide some tricks for
such cases which are currently not implemented by the compiler?
[ Expressions in type context ]
Additionally, names
in a type expression are resolved to their full form (indicating their
origin, e.g. +$Integer). This gives the _expanded type expression_.
Might this kind of resolvement be a hint, why sometimes renaming a
variable turns a segfaulting program into a working one -- and vice-versa?
--
Kind regards,
Christian
_______________________________________________
Axiom-developer mailing list
Axiom-developer@nongnu.org
http://lists.nongnu.org/mailman/listinfo/axiom-developer