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

Bienlein jeti789 at web.de
Wed Feb 28 08:45:00 UTC 2018


On Monday, 26 February 2018 at 19:36:33 UTC, Simen Kjærås wrote:
> 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

Didn't have time so far to look into this. But thanks anyway.


More information about the Digitalmars-d mailing list