On Friday, 26 May 2017 at 11:18:44 UTC, Stanislav Blinov wrote:
On Friday, 26 May 2017 at 09:59:26 UTC, zakk wrote:
Hello everyone,
I just started using D and I am a bit puzzled by the syntax of
the sort function is std.algorithm.sorting, which is
sort!(comparingFunction)(list)
where comparingFunction is often a lambda expression. For
instance in the Wolfram Language the equivalent function is
Sort[list,comparingFunction]
My questions are:
1) Why is D making using of the binary ! operator, which as
far as I understand introduces a template?
The ! operator is needed to distinguish template arguments,
passed and known at compile time, from actual function
arguments, passed and known at run time. "!" doesn't
"introduce" a template. The definition of 'sort' is a template,
sort!(fn)(list) is an instantiation of that template with
concrete arguments.
In C++, template arguments are denoted with <>, which is more
verbose and introduces syntax ambiguity in complex templates. D
avoids that by using the !.
2) Why is a template needed here?
Templates are a form of polymorphism that works at compile
time. It allows the programmer to write, and the compiler to
generate, the most efficient an/or the most practical code
given the concrete use case. The net effect is that at runtime
you get the sorting function that is tailored for the specific
types and comparison predicate, as if it was written by hand.
3) It seems to me like the argument passed to the template is
a lambda expression. I only know about templates taking types
as argument. What's going on?
In D, depending on their definition, templates can take types,
values or symbols as arguments. In this case, sort takes the
comparison function and inserts it directly into the algorithm,
which enables the compiler to inline it and/or perform various
other optimizations, which would've been harder or impossible
to do if the function was only known at runtime.
Also, this enables writing concise code: in Phobos, algorithms
that take predicates allow to pass them as string literals
instead of full-blown functions:
sort!"a < b"(list);
The "a < b" will be transformed at compile time into (a, b) =>
a < b.
Thanks Gary and Stanislav for your replies.
I have a followup question: my background is C and in Wolfram
Mathematica, so my knowledge of templates is limited to trivial
examples in C++, like:
template <class T>
const T& min(const T& lhs, const T& rhs)
{
return lhs < rhs ? lhs : rhs;
}
where the template argument is a type, and the function does the
same job for different types.
It seems to me that when programming in D templates are something
more powerful, is it correct of thinking of them as some argument
which is known at compile time? Is this misleading?
Many thanks again for your replies!