Thread overview
Re: CommonType and non-built-in types
Oct 01, 2013
Artur Skawina
Oct 01, 2013
Dicebot
Oct 01, 2013
ilya-stromberg
Oct 01, 2013
Artur Skawina
October 01, 2013
On 10/01/13 12:50, Joseph Rushton Wakeling wrote:

> (4) Is there a good reason why there _shouldn't_ be a CommonType of (say) int and BigInt?

Define "CommonType". Ie it's a question of definition, and the language
does not have sufficient means to easily enough express that concept
("interface", "trait", whatever).
For built-in types, the "common" type can be determined by the built-in
conversion and promotion rules; the implemented interfaces (supported
operators etc) are all known. But this isn't true for user defined types
-- how is the compiler supposed to know that eg 'struct BigInt' can be
used in place of 'int'?

One (hacky) way to make this work, using today's 'D', would be something
like:

   void SUBTYPE(A, B)(A a, B b) {
      A x = b;
      x = b;
      x += b;
      x *= a + b;
      // etc
   }

   template CommonType(A, B, alias ST=SUBTYPE){
      static if (is(typeof(1?A.init:B.init) C))
         alias CommonType = C;
      else static if (is(typeof(ST!(A, B))))
         alias CommonType = A;
      else static if (is(typeof(ST!(B, A))))
         alias CommonType = B;
      else
         alias CommonType = void;
   }
   template CommonType(A...) if (A.length>2) {
      alias CommonType = CommonType!(CommonType!(A[0], A[1]), A[2..$]);
   }

You could specify the desired interface inside the SUBTYPE function --
if it successfully compiles with a pair of 'A' and 'B' types then 'A'
will be assumed to be the "common" type (ie functional subtype).
As written above, the code already works, evaluates
"CommonType!(byte, BigInt, long)" to 'BigInt' and could be used to
solve your problem.
But it's just an example, a lot is still missing; it will do the right
thing with builtin types thanks to the first static-if, but can make
many wrong choices when dealing with (multiple) user-defined types.
A generic solution would require language support, w/o that the result
would be too verbose, complicated, subtle and error-prone.

artur
October 01, 2013
Definition of common type is pretty simple - it is a type both types can be implicitly converted to. For `int` and `BigInt` common type should be `BigInt` if it was possible to define that implicit conversion. AFAIK it is not possible and thus they can't have common type.
October 01, 2013
On Tuesday, 1 October 2013 at 17:56:17 UTC, Dicebot wrote:
> Definition of common type is pretty simple - it is a type both types can be implicitly converted to. For `int` and `BigInt` common type should be `BigInt` if it was possible to define that implicit conversion. AFAIK it is not possible and thus they can't have common type.

Yes, we need implicit conversion support for usage cases like this.
May be only from build-in types to the user-defined as you said before, but it will be really useful.
I really don't know any usage example for implicit conversion from `int` to `BigInt` when it produces problems.
October 01, 2013
On 10/01/13 19:56, Dicebot wrote:
> Definition of common type is pretty simple - it is a type both types can be implicitly converted to.

It's a bit more complicated, even for the simple cases - for example two types that implicitly convert to a narrower type can (and usually should) have a different "common" type. In general, implicit conversions make things more "interesting".

> For `int` and `BigInt` common type should be `BigInt` if it was possible to define that implicit conversion. AFAIK it is not possible and thus they can't have common type.

Yes. In practice, though, the required interface for these types may not require
the missing functionality (eg function calls won't work, but both construction
and assignment will - and this can be enough). The traits-like /hacks/ can be
useful then. That's of course just a work-around, not an argument against introducing
user defined implicit conversions.

artur