[Aldor-l] [Aldor-combinat-devel] parametric types and instantiation

Christian Aistleitner tmgisi at gmx.at
Thu Oct 26 04:59:42 EDT 2006


Hello,

On Wed, 25 Oct 2006 13:57:10 +0200, Ralf Hemmecke <ralf at hemmecke.de> wrote:

>> In OO, you instantiate Dom.In Aldor, you evaluate Dom.
>
> But evaluating Dom at 1 and Dom at 2 creates (instantiates) two domains
> Dom(1) and Dom(2).

but to me, the difference is, that for parametric types in OO, you want
Dom( 1 ) to be the same domain no matter where it is used. In Aldor, you  
do not have this restriction. (We discussed it in a different thread some  
time ago)
In Aldor you have this requirement only, if Dom( 1 ) appears in type  
context.
Consider the following, tricky piece of code:

#include "aldor"

import from String;
import from TextWriter, Character, MachineInteger;


Cat: Category == with {
	getMagicNumber: () -> MachineInteger;
};

Dom( a: MachineInteger ): Cat == add {
	stdout << "initializing with " << a << newline;
	getMagicNumber(): MachineInteger == {
		a;
	}
}


func( EDom: Cat ): () == {
	EEDom: Cat == EDom add;
	import from EEDom;
	stdout << getMagicNumber() << newline;
}

func( Dom( 1 ) );
func( Dom( 1 ) );


Dom( 1 ) does not appear in type context directly. Hence it should be  
instantiated twice. And it is instantiated twice:

____________________________________________
tmgisi at spencer
cwd: ~/aldor
$ LC_ALL=C /opt/aldor/bin/aldor -M no-abbrev -C args=-Wopts=-m32 -Fx -l  
aldor test.as && ./test
cc1: note: -fwritable-strings is deprecated; see documentation for details
cc1: note: -fwritable-strings is deprecated; see documentation for details
initializing with 1
1
initializing with 1
1

In OO, the output of that example would cause serious troubles. In Aldor,  
it's perfectly valid.

>> In OO, instantiation of Dom always carries a (at least conceptional)
>> connection to Dom.In Aldor the result of Dom( A ) is (hopefully)
>> completely decoupled from  Dom and A, just as the result 7 of add( 3,
>> 4 ) is completely decoupled   from add, 3, and 4.
>
> I think, I cannot confirm that Dom(1) does not carry information about
> Dom and 1.

Mapxe, my previous paragraph wasn't as clear as it should be.
The result of Dom( A ) should not know that it is the result of applying A  
to Dom.
Let me explain what I mean with the help of the example you provided:

> ---BEGIN aaa.as
> #include "aldor"
> #include "aldorio"
>
> define CatA(T: PrimitiveType): Category == with;
> define CatB(T: PrimitiveType): Category == with;
> DomA(T: PrimitiveType): CatA(T) == add;
> DomB(T: PrimitiveType): CatB(T) == add;
> stdout << (DomA(Integer) has CatA(Integer)) << newline;
> stdout << (DomA(Integer) has CatA(String)) << newline;
> stdout << (DomA(Integer) has CatB(Integer)) << newline;
> stdout << (DomA(Integer) has with) << newline;
> ---END aaa.as

As your example also uses functions mapping to categories, let me start  
with these Categories, as they further complicate things.

What is CatA( Integer )?
CatA( Integer ) is the application of Integer to the function CatA.
The result is a new, empty category.

What is CatA( String )?
CatA( String ) is the application of String to the function CatA.
The result is another, new, empty category.

These two categories are not equal. First of all, they live at different  
places in memory. They have different exports.
The result of CatA( Integer ) exports itself.
The result of CatA( String ) exports itself.
Both of CatA( Integer ) and CatA( String ) occur in type context.  
Therefore, CatA should return the same category each type it is evaluated  
at Integer. Therefore, CatA should return the same category each type it  
is evaluated at String.

The self exports do not couple the categories with being the result of a  
function evaluation.

Now on to DomA( Integer ).
DomA( Integer ) is again a function call. Integer is applied to DomA.
When calling this function its type creating function (CatA) is evaluated  
at the actual parameter value of T (i.e.: Integer ). Hence, the type of  
the result of evaluating DomA at Integer is CatA( Integer ).
As CatA( Integer ) appears in type context, it holds the unique value as  
described above.
The value of the result of the application of Integer to DomA is just some  
new, empty domain.

Note, that through the evaluation of DomA at Integer, the returned  
parameter is/should be equivalent to

SomeName: Cat( Integer ) == add;

where Cat( Integer ) could be replaced by some constant as well. The  
important part of decoupling is, that the result of the application of  
Integer to DomA has no notion of being the result of the application of  
Integer to DomA.
Of course, Integer appears within its definition. But the semantic of this  
Integer is now really, plainly Integer and no longer some actual parameter  
value within some function call.

> Actually I don't know for domains, but for categories how
> would the following be possible then?

I'll discuss the results step by step. Let me first note, that  
DomA( Integer ) gives the same value again and again. It appears natural  
to me that it should be in type context due to the “has” constructs, but  
according to the AUG, “has" does not form a type context -- at least it is  
not mentioned.
I furthermore assume, that “the type context because of ‘has’” has been  
forgotten in the AUG and consider DomA( Integer ) in type context.

>  >aldor -grun -laldor aaa.as

> T
due to
> stdout << (DomA(Integer) has CatA(Integer)) << newline;

The type of the result of DomA(Integer) contains the only evaluation of  
CatA(Integer). Of course, this yields true. But at this point now,  
DomA(Integer) refers to the result of the application, hence to the  
construct SomeName above, which is decoupled from DomA and its parameter  
Integer. Same holds for CatA( Integer ).

> F
due to
> stdout << (DomA(Integer) has CatA(String)) << newline;

CatA( String ) yields a different category as CatA( Integer ) does -- as  
explained above. DomA( Integer ) only exports CatA( Integer ) and not  
CatA( String ). Hence, false.

> F
due to
> stdout << (DomA(Integer) has CatB(Integer)) << newline;

CatB( Integer ) gives a third category, exporting no function, but only  
itself. DomA( Integer ) again does not export this third category, hence  
false.

> T
due to
> stdout << (DomA(Integer) has with) << newline;

Here you introduce another category. An anonymous one. Anonymous  
categories do not export themselves as far as I can tell. Therefore,  
“with” is a completely empty category, which is exported by every domain.  
Therefore, true.


> If CatA and DomA where really functions then the second line should give
> true since neither the DomA nor CatA actually depend on their parameter.

Hopefully, my explanations made clear, what I meant by the decoupling.

Kind regards,
Christian



More information about the Aldor-l mailing list