www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Mixin overload sets

reply "BLM768" <blm768 gmail.com> writes:
The current behavior of placing identically-named functions from 
separate mixins into separate overload sets works well most of 
the time, but there are cases when the functions should be in the 
same overload set, and the aliasing required to allow overloading 
can quickly get tedious and clutter the namespace where the 
mixins are used, especially if the mixins define multiple 
functions.

mixin template someMixin(Args ...) {
   void abc(Args) {};
   void def(int, Args);
}

struct HasMixins {
   mixin someMixin!int mixinInt;
   alias mixinInt.abc abc;
   alias mixinInt.def def;
   mixin someMixin!float mixinFloat;
   alias mixinFloat.abc abc;
   alias mixinFloat.def def;
   //and so on...
}

It would be nice if we had a more concise way to pull all of the 
duplicate functions into a single overload set. I can think of 
two ways to handle this:

1. Introduce a new syntax.

struct HasMixins {
   //One possible syntax:
   alias mixin someMixin!int this;
   alias mixin someMixin!float this;
   //etc.
}

HasMixins hm;
hm.abc(3f); //Would call HasMixins.abc(float)

2. Automatically place functions that come from different 
instances of the same mixin template into the same namespace.

struct HasMixins {
   mixin someMixin!int;
   mixin someMixin!float;
}

HasMixins hm;
hm.abc(3f); //Would call HasMixins.abc(float)

mixin template someOtherMixin {
   void abc() {};
}

struct HasOtherMixins {
   mixin someMixin!int;
   mixin someMixin!float;
   mixin someOtherMixin;
}

HasOtherMixins hm2;
hm2.abc(3f); //error

Thoughts?
Aug 14 2013
next sibling parent "QAston" <qaston gmail.com> writes:
On Wednesday, 14 August 2013 at 17:35:28 UTC, BLM768 wrote:
 The current behavior of placing identically-named functions 
 from separate mixins into separate overload sets works well 
 most of the time, but there are cases when the functions should 
 be in the same overload set, and the aliasing required to allow 
 overloading can quickly get tedious and clutter the namespace 
 where the mixins are used, especially if the mixins define 
 multiple functions.

 mixin template someMixin(Args ...) {
   void abc(Args) {};
   void def(int, Args);
 }

 struct HasMixins {
   mixin someMixin!int mixinInt;
   alias mixinInt.abc abc;
   alias mixinInt.def def;
   mixin someMixin!float mixinFloat;
   alias mixinFloat.abc abc;
   alias mixinFloat.def def;
   //and so on...
 }

 It would be nice if we had a more concise way to pull all of 
 the duplicate functions into a single overload set. I can think 
 of two ways to handle this:

 1. Introduce a new syntax.

 struct HasMixins {
   //One possible syntax:
   alias mixin someMixin!int this;
   alias mixin someMixin!float this;
   //etc.
 }

 HasMixins hm;
 hm.abc(3f); //Would call HasMixins.abc(float)

 2. Automatically place functions that come from different 
 instances of the same mixin template into the same namespace.

 struct HasMixins {
   mixin someMixin!int;
   mixin someMixin!float;
 }

 HasMixins hm;
 hm.abc(3f); //Would call HasMixins.abc(float)

 mixin template someOtherMixin {
   void abc() {};
 }

 struct HasOtherMixins {
   mixin someMixin!int;
   mixin someMixin!float;
   mixin someOtherMixin;
 }

 HasOtherMixins hm2;
 hm2.abc(3f); //error

 Thoughts?

You can put those functions into HasOtherMixins by using alias. struct HasOtherMixins { ... alias someMixin!int.abc abc; alias someMixin!float.abc abc; alias someOtherMixin abc; }
Aug 16 2013
prev sibling next sibling parent "QAston" <qaston gmail.com> writes:
On Friday, 16 August 2013 at 07:48:52 UTC, QAston wrote:
 On Wednesday, 14 August 2013 at 17:35:28 UTC, BLM768 wrote:
 The current behavior of placing identically-named functions 
 from separate mixins into separate overload sets works well 
 most of the time, but there are cases when the functions 
 should be in the same overload set, and the aliasing required 
 to allow overloading can quickly get tedious and clutter the 
 namespace where the mixins are used, especially if the mixins 
 define multiple functions.

 mixin template someMixin(Args ...) {
  void abc(Args) {};
  void def(int, Args);
 }

 struct HasMixins {
  mixin someMixin!int mixinInt;
  alias mixinInt.abc abc;
  alias mixinInt.def def;
  mixin someMixin!float mixinFloat;
  alias mixinFloat.abc abc;
  alias mixinFloat.def def;
  //and so on...
 }

 It would be nice if we had a more concise way to pull all of 
 the duplicate functions into a single overload set. I can 
 think of two ways to handle this:

 1. Introduce a new syntax.

 struct HasMixins {
  //One possible syntax:
  alias mixin someMixin!int this;
  alias mixin someMixin!float this;
  //etc.
 }

 HasMixins hm;
 hm.abc(3f); //Would call HasMixins.abc(float)

 2. Automatically place functions that come from different 
 instances of the same mixin template into the same namespace.

 struct HasMixins {
  mixin someMixin!int;
  mixin someMixin!float;
 }

 HasMixins hm;
 hm.abc(3f); //Would call HasMixins.abc(float)

 mixin template someOtherMixin {
  void abc() {};
 }

 struct HasOtherMixins {
  mixin someMixin!int;
  mixin someMixin!float;
  mixin someOtherMixin;
 }

 HasOtherMixins hm2;
 hm2.abc(3f); //error

 Thoughts?

You can put those functions into HasOtherMixins by using alias. struct HasOtherMixins { ... alias someMixin!int.abc abc; alias someMixin!float.abc abc; alias someOtherMixin abc; }

Ah, I just saw you did that in the beginning of the post. I blame missing that to writing this early in the morning :)
Aug 16 2013
prev sibling parent "BLM768" <blm768 gmail.com> writes:
On Friday, 16 August 2013 at 07:48:52 UTC, QAston wrote:
 You can put those functions into HasOtherMixins by using alias.
 struct HasOtherMixins {
 ...
 alias someMixin!int.abc abc;
 alias someMixin!float.abc abc;
 alias someOtherMixin abc;
 }

Actually, that syntax only works for regular templates, not mixins. Trying it with a mixin template gives an error. It's also not very useful when mixing in several methods from the same template. However, the first solution I suggested could be expanded to support that type of syntax: struct HasMixins { alias mixin someMixin!int.abc abc; //etc. } I'm starting to lean toward the first option as the more "correct" solution because it's more flexible and follows the principle of least surprise. If it's decided that this would be an acceptable addition to the language, I could try to cobble a pull request together. I don't have any experience with the DMD codebase, but it might be a good introductory project for me...
Aug 16 2013