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.