Can this be done? Defining type as in this Scala sample code

Simen Kjærås simen.kjaras at gmail.com
Mon Feb 26 19:36:33 UTC 2018


On Monday, 26 February 2018 at 15:43:54 UTC, Bienlein wrote:
> object Scratch extends App {
>
>   // compiles:
>
>   val list = List(1, 2.4, 5)
>   val sum = list.sum
>   println(sum)
>
>
>   // does not compile:
>
>   val list2 = List(1, 2.4, 5, "123")
>   val sum2 = list2.sum
>   println(sum2)
>
> }

There's nothing in the language or standard library that supports 
this. However, it's perfectly possible to make something with 
those semantics:

import std.variant;
import std.stdio;

struct List(T) {
     T[] values;

     alias values this;
}

auto list(T...)(T args)
{
     import std.traits : CommonType;

     static if (is(CommonType!T == void))
         List!Variant result;
     else
         List!(CommonType!T) result;

     result.length = T.length;
     foreach (i, e; args) {
         result[i] = e;
     }
     return result;
}

auto sum(T)(List!T lst)
if (is(typeof(lst[0] + lst[0])) && !is(T == Variant))
{
     T result = 0;
     foreach (e; lst) {
         result += e;
     }
     return result;
}

unittest {
     auto list1 = list(1, 2.4, 5);
     auto sum1 = list1.sum;
     writeln(sum1);

     auto list2 = list(1, 2.4, 5, "123");
     auto sum2 = list2.sum;
     writeln(sum2);
}


Since std.variant.Variant does operator overloads, we have to 
explicitly check if T == Variant in the sum function. For 
Variant, that's probably the correct choice. We could use 
Algebraic instead, but it also does operator overloads, even when 
no type in its arguments support them. Again, we could create our 
own - Algebraic and Variant are library types, after all.

--
   Simen


More information about the Digitalmars-d mailing list