[Aldor-l] exports and constants

Ralf Hemmecke ralf at hemmecke.de
Thu Jul 20 07:11:35 EDT 2006


Hello,

Sorry, but Christian and me started that discussion in German, but we 
now think that it might be interesting for all other Aldor people.

So let me start with a little program that shows some strange behaviour.

---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?

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?

Let me go on with answering Christian's mail...

On 07/20/2006 11:05 AM, Christian Aistleitner wrote:
> On Wed, 19 Jul 2006 11:20:06 +0200, Ralf Hemmecke <ralf at hemmecke.de> wrote:
> 
>>> i: Integer == 1;
>>>  und
>>>  i: Integer == 2;
>>>  nicht gleich sind.
>>
>> Naja, hier muß man nur wissen, daß die Symbole 0 und 1 Ausnahmen in 
>> Aldor sind. Die kann man nämlich als Bezeichner verwenden, während das 
>> bei 2 nicht geht. Weil das einfach ein Symbol ist, das wie eine ganze 
>> Zahl aussieht, aber niemals ein Bezeichner sein kann. (Letzteres ist 
>> eigentlich auch eine Einschränkung, sonst könnte man "PowerSet(S)" 
>> ganz einfach als "2^S" implementieren. OK, dann wäre der Bezeichner 
>> allerdings "2^"... naja.
> 
> Sorry that was a bad example. 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?

 > 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).

>> One cannot, however write something like
>>
>> CatC: Category == with { }
>> H: CatC == Dom;
> 
> Of Course not, because Dom does not provide CatC.

>> Different from
>>
>> A: CatA == Dom add;
>>
>> the construct
>>
>> H: CatA == Dom;
>>
>> just means that H provides *at least* the exports of CatA, and the compiler can
>> tell, if Dom provides less.
> 
> You can interprete both kinds as "provides at least". But the first 
> statment does not give you any more than CatA.

>> It is going to be interesting.
>>
>> Take for example
>>
>> A: Join(CatA, CatX) == add {...}
>> B: Join(CatB, CatX) == add {...}
>> X: CatX == if odd? random() then A else B;
>>
>> It is clear that X cannot export more than CatX. In such constructions
 >> the additional exports of A and B cannot be seen.
> 
> I am a bit puzzled right now. The line
> 
>> X: CatX == if odd? random() then A else B;
> 
> causes problems and does not compile. Furthermore, for
> 
>> X: CatX == A
> 
> X has both CatA and CatX, as expected ... Could you detail on that problem.

Sorry, I have not tested that line and I also cannot compile it.

---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 (*)?

> 
>> R: GcdDomain == if iWantRationals? then Fraction Integer else Integer;
>> computation()$MyPackage(R);
>>
>> Und in MyPackage haben wir sowas
>>
>> gcd(a: R, b: R): R == {
>>    if R has Field then {
>>        ... kann nur 0 oder 1 sein
>>    } else {
>>       ... implement Euclidean Algorithm
>>    }
>> }
>>
>> und computation() benutzt intern diesen gcd. Selbst wenn
>> iWantRationals? = true
>> wird nicht der einfachere Körperfall genommen. MyPackage sieht also 
>> die zusätzlichen Exports nicht mehr. Blöd, was?
> 
> This puzzles me even more, because it works properly for me:
> 
> #include "algebra"
> import from String, TextWriter, Character;
> import from MachineInteger;
> 
> #if FIELD
> firstIsField? == true;
> #else
> firstIsField? == false;
> #endif
> R: GcdDomain == if firstIsField? then (Fraction Integer at GcdDomain) else 
> (Integer at GcdDomain);
> 
> stdout << ( R has GcdDomain ) << newline;
> stdout << ( R has Field ) << newline;

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 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.

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.

Ralf





More information about the Aldor-l mailing list