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