I must confess I didnt read your whole posting to the end,
but it seems that this is much the same idea as I had in
"Feature Request: interfaces declare types" plus some extra
intelligence, or?
Henning
--
GPG Public Key: http://keyserver.veridis.com:11371/search?q=0x41911851
Fingerprint: 344F 4072 F038 BB9E B35D E6AB DDD6 D36D 4191 1851

On Fri, 25 May 2007 21:48:10 +0400, Henning Hasemann <hhasemann@web.de>
wrote:
> I must confess I didnt read your whole posting to the end,
> but it seems that this is much the same idea as I had in
> "Feature Request: interfaces declare types" plus some extra
> intelligence, or?
As I can see your idea is very close to 'abstract members' in Scala:
class Demo {
type A // This member must be defined in a derived class.
// There isn't any restruction to type A.
type B <: Another // This is another member which must be
// defined in a derived class.
/* ... In the body of class Demo names A and B can be
used as template parameters in D templates ... */
}
This looks similar to your proposal:
interface ContainerIterator(T) {
T content();
}
interface Container(T) {
type Iterator : ContainerIterator!(T); // Like Scala's 'type Iterator <:
ContainerIterator[T]'
T first();
void remove(T);
Iterator(T) firstIterator();
void remove(Iterator(T));
}
JFYI: There is a citation from 'Scalable Component Abstractions':
\begin{quote}
...
Abstract type members provide a fexible way to abstract over concrete
types of components. Abstract types can hide information about internals
of a component, similar to their use in SML signatures. In an
object-oriented framework where classes can be extended by inheritance,
they may also be used as a fexible means of parameterization (often called
family polymorphism [11]).
...
[11] E. Ernst. Family polymorphism. In Proceedings of the European
Conference on Object-Oriented Programming, pages 303-326, Budapest,
Hungary, 2001.
\end{quote}
So it seems that you reinvent the idea about 'abstract type members' ;)
But I speak about another Scala's feature: selftypes. For example:
template Demo(S) {
class Dumpable {
void dump(S stream) {
stream.put( this ); // At this point 'this' is MyClass.
}
}
}
My proposal is to tell the compiler that 'this' in MyClass has type T or
any of its subclass:
template Demo(S, T) {
class Dumpable is T {
void dump(S stream) {
stream.put( this ); // At this point 'this' is T.
}
}
}
class MyStream {
void put( MyClass obj ) { ... }
}
class MyClass : Demo!( MyStream, MyClass ).Dumpable {
...
}
auto myStream = new MyStream;
auto my = new MyClass;
my.dump( myStream ); // Method MyStream.put(MyClass) must be called.
--
Regards,
Yauheni Akhotnikau

eao197 wrote:
> On Fri, 25 May 2007 21:48:10 +0400, Henning Hasemann <hhasemann@web.de>
> wrote:
> [...]
> class Demo {
> type A // This member must be defined in a derived class.
> // There isn't any restruction to type A.
>
> type B <: Another // This is another member which must be
> // defined in a derived class.
>
> /* ... In the body of class Demo names A and B can be
> used as template parameters in D templates ... */
> }
Your use case is a form of metatyping. In the Subject/Observer example,
you notice that the types S and O may be template parameters, but you
want to restrict their type to be subtypes of the nested
Subject/Observer types. That is, you want to provide metatypes for the
S and O metaparameters.
> This looks similar to your proposal:
>
> interface ContainerIterator(T) {
> T content();
> }
>
> interface Container(T) {
> type Iterator : ContainerIterator!(T); // Like Scala's 'type Iterator
> <: ContainerIterator[T]'
>
> T first();
> void remove(T);
> Iterator(T) firstIterator();
> void remove(Iterator(T));
> }
And this is also a form of metatyping. In this case, we want to declare
that the dependent type Iterator(T) has a metatype of
ContainerIterator(T) (that is, we minimize the set of possible values
(types) that Iterator(T) can have by defining the nature of those values
in terms of a metafunction...or, to put it another way, Iterator(T) is
an algebraic metatype).
> JFYI: There is a citation from 'Scalable Component Abstractions':
> \begin{quote}
> [...]
> So it seems that you reinvent the idea about 'abstract type members' ;)
Or rather, the CS community does not have a unified notion of metatyping
and is inventing terms as they go.
> [...]
> My proposal is to tell the compiler that 'this' in MyClass has type T or
> any of its subclass:
>
> template Demo(S, T) {
> class Dumpable is T {
> void dump(S stream) {
> stream.put( this ); // At this point 'this' is T.
> }
> }
> }
>
> class MyStream {
> void put( MyClass obj ) { ... }
> }
>
> class MyClass : Demo!( MyStream, MyClass ).Dumpable {
> ...
> }
> [...]
This particular example isn't very motivating because you would
typically just do this:
void dump(T)(S stream, T obj)
{
stream.put(obj);
}
In general, this is equivalent to the CRTP in C++, which has the general
form in D of:
class Derived : RecurringBase!(Derived)
{ ... }
As with any recurrence pattern, you have to be careful about what is
allowed and what isn't, or you may end up with an infinitely nested
definition. For instance, if RecurringBase(T) is allowed to derive from
T, you get the regress. However, D prevents this because T is a forward
reference at instantiation time.
I'm not sure what the value-add of the "self type" is when the CRTP is
available in D:
class Base(T) { T x; }
class Derived : Base!(Derived) { int x; }
void main() { Derived d; }
This is a perfectly valid D program according to dmd.
Dave

On Sat, 26 May 2007 08:21:48 +0400, David B. Held
<dheld@codelogicconsulting.com> wrote:
> In general, this is equivalent to the CRTP in C++, which has the general
> form in D of:
>
> class Derived : RecurringBase!(Derived)
> { ... }
>
> As with any recurrence pattern, you have to be careful about what is
> allowed and what isn't, or you may end up with an infinitely nested
> definition. For instance, if RecurringBase(T) is allowed to derive from
> T, you get the regress. However, D prevents this because T is a forward
> reference at instantiation time.
>
> I'm not sure what the value-add of the "self type" is when the CRTP is
> available in D:
>
> class Base(T) { T x; }
> class Derived : Base!(Derived) { int x; }
> void main() { Derived d; }
>
> This is a perfectly valid D program according to dmd.
Could you rewrite my initial example with Subject/Observer with using CRTP
technique?
--
Regards,
Yauheni Akhotnikau

eao197 wrote:
> On Sat, 26 May 2007 08:21:48 +0400, David B. Held
> <dheld@codelogicconsulting.com> wrote:
>
>> In general, this is equivalent to the CRTP in C++, which has the general
>> form in D of:
>>
>> class Derived : RecurringBase!(Derived)
>> { ... }
>>
>> As with any recurrence pattern, you have to be careful about what is
>> allowed and what isn't, or you may end up with an infinitely nested
>> definition. For instance, if RecurringBase(T) is allowed to derive from
>> T, you get the regress. However, D prevents this because T is a forward
>> reference at instantiation time.
>>
>> I'm not sure what the value-add of the "self type" is when the CRTP is
>> available in D:
>>
>> class Base(T) { T x; }
>> class Derived : Base!(Derived) { int x; }
>> void main() { Derived d; }
>>
>> This is a perfectly valid D program according to dmd.
>
> Could you rewrite my initial example with Subject/Observer with using CRTP
> technique?
You're using it already in the first post. The two classes are packaged
inside a single template so it might not seem so obvious.

On Sat, 26 May 2007 14:28:27 +0400, Jari-Matti Mäkelä
<jmjmak@utu.fi.invalid> wrote:
>>> Can you show how this would work if there were multiple subclasses
>>> of 'Subject' and 'Observer'? (for example multiple sensor types in the
>>> SensorReader example) Does it require language support for multiple
>>> dispatch then?
>>
>> Do you what [sic] to see Scala example?
Sorry, it is a typo. I mean: 'Do you want to see Scala example?'
>
> Yes, please :)
It is not a simple task for me, because I'm not a Scala programmer. I've
tried to make a sample today but without success. So I ask my friends to
help me with it. Now I'm waiting their replies. So I hope to publish such
example some time later.
--
Regards,
Yauheni Akhotnikau