On Monday, 26 February 2018 at 15:43:54 UTC, Bienlein wrote:
Hello,
just curious whether this is a Scala speciality or whether it
could also be done in D. Here is some Scala code:
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)
}
In the code above list.sum compiles, because list only contains
values that are of type Numeric. The sum method looks like this:
def sum[B >: A](implicit num: Numeric[B]): B =
foldLeft(num.zero)(num.plus)
So sum compiles if all values can be converted to Numeric which
the compiler checks at compile time.
For list2 this is not the case as "123" is a string and
therefore not of type Numeric. Calling functions on list2 ist
fine as long as no function is called that requires a
conversion to Numeric for each element in the list such as in
the case of sum.
My question is now whether that kind of logic can also be
defined in D. My knowledge of D is too limited to find out in
reasonable time myself. Reason for my curiosity is that the
Scala solution relies on implicit conversion at compile time
which has its drawbacks (compilation times, colliding implicit
conversions the compiler cannot detect, etc.). So I just wanted
to see whether D does this in a clean way and I know that D
allows for some type parameter constraints to be set.
Thansk for any answers,
Bienlein
Probably more appropriate in the Learn forum.
I don't really know much Scala, but it seems like
val list2 = List(1, 2.4, 5, "123")
would fail to compile because List requires the values to be of a
common type and "123" is a string. By contrast, a tuple could
hold all those elements, but then it might fail when calculating
the sum. Even in D, it's a little tricky to take the sum of a
Tuple. You may as well just do a for loop.
So I suppose the question is can D do
val list = List(1, 2.4, 5)
val sum = list.sum
Phobos has list containers in std.container. However, usually you
would use an array for something like this unless you have a
reason to use a list. The 1 and 5 ints are implicitly casted to
doubles in both versions.
//array version
import std.algorithm : sum;
import std.stdio : writeln;
void main()
{
auto x = [1, 2.4, 5];
writeln(x.sum);
}
//list version
import std.algorithm : sum;
import std.stdio : writeln;
import std.container : SList;
void main()
{
auto x = SList!double(1, 2.4, 5);
writeln(x[].sum);
}