[Aldor-l] exports and constants

Christian Aistleitner tmgisi at gmx.at
Fri Jul 21 02:38:25 EDT 2006


Hello,

> ---BEGIN aaa.as
> #include "aldor"
> import from String, TextWriter, Character;
>
> define CatA: Category == with { }
> define CatB: Category == with { }
> define SomeCat: Category == with { CatA; CatB; }
> Dom: SomeCat == Integer add;
>
> A == Dom;
> B: CatA == Dom;
> H: CatA == Dom add;
>
> stdout << "A has CatA: " << ( A has CatA ) << newline;
> stdout << "A has CatB: " << ( A has CatB ) << newline;
> stdout << "B has CatA: " << ( B has CatA ) << newline;
> stdout << "B has CatB: " << ( B has CatB ) << newline;
> stdout << "H has CatA: " << ( H has CatA ) << newline;
> stdout << "H has CatB: " << ( H has CatB ) << newline;
> ---END aaa.as
>
> You get...
>  >aldor -grun -laldor xxx.as
> A has CatA: T
> A has CatB: T
> B has CatA: T
> B has CatB: T
> H has CatA: T
> H has CatB: F
>
> In particular, that "B has CatB" is a bit surprising, isn't it?

however, when comparing it to other languages (e.g.: Java), there is  
always the difference between the dynamic and the static type of an  
object. Hence, it is natural to work with the "the dynamic type provides  
at least the static type" principle.

Maybe I completely lost my point now (probably), but isn't it good that B  
has CatB?
If B would not have CatB, things like

func( R: Ring, a: R, b: R ): R == {
	if R has Field then
	{
		a / b;
	} else {
		a * b;
	}
}


would never allow to enter the true branch of the if statment.
Consider
   func( Fraction Integer, 1, 1 )
. It can be rewritten to

--creating new scope
...
--fixing parameter values in new scope
R: Ring == Fraction Integer;
a: R == 1;
b: R == 1;

--entering function body
if R has Field then
{
	a / b;
} else {
	a * b;
}

which connects it to our discussion. So I guess the fact "B having CatB"  
is essential!


But why is "H has CatB" false?
I (now) like that as well. So the add is kind of a "forget" operator.
It allows you to chop off parts of a domain you do not need--or would  
break the semantics.
AdditivieButNotArithmeticInteger: AdditiveType == Integer add;

Then AdditivieButNotArithmeticInteger is not of type ArithmeticType.

> Has someone found a description in the Aldor UG of whether this is
> intended to be so or this should be considered a bug in the compiler?

It's not a bug; it's a feature.

>> What I wanted to point out is that from a
>> user perspective,
>>
>>   identifier: type == value
>>
>> should always refer to the same language construct. So
>>
>>   i: Integer == 2;
>>
>> and
>>
>>   i: Integer == 3;
>>
>> should be the same language construct,
>
> Where do you see a difference?

I do not see a difference between 2 and 3. That is the point. I also do  
not see a difference between "Domain" and "Domain add". Both are domains  
(However different ones of course, just as 2 is not equal to 3).

>  > just as
>>
>>   Ident: Category == Domain;
>>
>> and
>>
>>   Ident: Category == Domain add;
>>
>> . Of course, "Domain" and "Domain add" are different things. No doubt
>> about that. However, this differenc should be the only difference.
>
> There is a difference in the semantic, but I cannot remember that I have
> found a proper explanation of what "Ident: SomeType == Dom" actually
> means (no "add" here).

So you mean the "Ident: SomeType == " part means two different things,  
regarding whether "Domain" or "Domain add" follows?
(It is obvious that "Domain" and "Domain add" are two different things,  
but we agreed on that before).

> ---BEGIN aaa2.as
> #include "aldor"
> import from String, TextWriter, Character;
>
> define CatA: Category == with;
> define CatB: Category == with;
> define CatX: Category == with;
>
> A: CatX with { CatA } == add;
> B: CatX with { CatB } == add;
>
> X: CatX == if true then (A add) else (B add); -- (*)
>
> stdout << "X has CatA: " << ( X has CatA ) << newline;
> stdout << "X has CatB: " << ( X has CatB ) << newline;
> stdout << "X has CatX: " << ( X has CatX ) << newline;
> ---END aaa2.as
>
> aldor -grun -laldor aaa2.as
> X has CatA: F
> X has CatB: F
> X has CatX: T
>
> That is clear, but why does the compiler reject the program without the
> "add" in line (*)?

I'd consider that a bug in comparison of exports. Replacing your (*) line  
by

   X: CatX == if true then (A at CatX) else (B at CatX);

gives a working program with output

   X has CatA: T
   X has CatB: F
   X has CatX: T

. So the problem (wild guess) is that the compiler Has problems with  
seeing that the if statement gives CatX in both branches of the if  
statement. Mainly because the types of A and B aro not equal. However, you  
can hint the compiler. My code is telling him "The if part gives CatX and  
the else part gives CatX". Then the compiler can infer, that the whole  
"if" statement gives CatX. And it is at least the type of X (which is  
CatX). So it matches.

However, your (*) with the "add"s tells the compiler to build two new  
domains. This is not giving hints to the compiler, but forcing it to do  
extra work and forcing it to produce extra code. However, due to the add,  
it (probably) tries to cut off all parts of A and B, it does not need. The  
compiler knows (due to the type CatX of X) that the "if" statement has to  
be of CatX. Therefore, both branches of the "if" statement have to provide  
CatX. So A is cut down to CatX and so is B.

> [ ... ]
> I am actually a bit amazed that your program runs and gives expected
> results. But what about...
>
> ---BEGIN aaa3.as
> #include "aldor"
> import from String, TextWriter, Character, MachineInteger;
>
> define CatA: Category == with;
> define CatB: Category == with;
> define CatX: Category == with;
>
> A: Join(CatX, CatA) == add;
> B: Join(CatX, CatB) == add;
>
> MyPkg(X: CatX): with {isA?: () -> Boolean} == add {
> 	isA?(): Boolean == X has CatA;
> }
> main(): () == {
> 	import from CommandLine, Array String;
> 	X: CatX == if zero? #arguments then (A add) else (B add);
> 	stdout << isA?()$MyPkg(X) << zero? #arguments << newline;
> }
> main();
> ---END aaa3.as
>
>  >aldor -fx -laldor aaa3.as
>  >aaa3
> FT
>  >aaa3 1
> FF
>
> It is clear with the "add" in the definition of X that we will always
> see a F in the first column of the output. Can someone find a "nice"
> construction where X is defined by a similar "if" construction and the
> first F would turn into T?

Of course. Again, be nice to the compiler. He is old. He is buggy. He is a  
bit rusty on the edges. And he is locked in, in a jail of non-free source  
code. But help him. Do not force him to do extra work. Tell him what you  
know, if he noods to be told.

X: CatX == if zero? #arguments then (A at CatX) else (B at CatX);

does the trick for me:

LC_ALL=C /opt/aldor/bin/aldor -M no-abbrev -C args=-Wopts=-m32 -Fx  
-lalgebra -laldor aaa3.as && ./aaa3 && ./aaa3 xx
cc1: note: -fwritable-strings is deprecated; see documentation for details
cc1: note: -fwritable-strings is deprecated; see documentation for details
TT
FF

> Of course it would be easy to write
>
> main(): () == {
> 	import from CommandLine, Array String;
> 	b: Boolean := zero? #arguments;
> 	stdout << (if b then isA?()$MyPkg(A) else isA?()$MyPkg(B));
> 	stdout << zero? #arguments << newline;
> }
>
> and obtain TT and FF, but that is not a "nice" solution.

I hope we both deem my solution to be "nice" :)

> Imagine there where another 2 domains R and S that would take a domain
> of type CatX as input and return a domain whose exports depend on the
> input. (A polynomial construction Dense/Sparse (for R and S) over some
> coefficient domain (for A and B) would be a common example.)
>
> It's soon becoming quite cumbersome and unreadable if it is done in the
> way the last main() function demonstrates.

I am not sure what to think of these last two paragraphs. I assume, they  
do not form a new problem, but underpin the demonstrated one.


--
Kind regards,
Christian




More information about the Aldor-l mailing list