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.

Reply via email to