The syntax of sort and templates

Mike Parker via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Fri May 26 04:22:47 PDT 2017


On Friday, 26 May 2017 at 09:59:26 UTC, zakk wrote:

> My questions are:
>
> 1) Why is D making using of the binary ! operator, which as far 
> as I understand introduces a template?

The ! operator *instantiates* a template. Whenever you need to 
specify compile-time arguments to match the template parameters, 
you need to use !. Templated functions are implemented like this:

template myTemplateFunc(<Template parameters go here>) {
     void myTemplateFunc(<Function parameters go here>) {
         ....
     }
}

Template parameters are used at compile time, usually to generate 
the code for the function, and function parameters are used at 
runtime. When the template and the function have the same name, 
you can shorten the declaration like so:

void myTemplateFunc(<Template parameters>)(<Function parameters>);

With many templated functions, the template parameters can be 
inferred by the compiler from the function parameters:

void myFunc(T)(T arg) {...}

In this case, you can call myFunc using the instantiation 
operator:

myFunc!(int)(10);

Or, since the compiler has enough information to infer T (10 is 
an int, arg is a T, therefore T is int), you can call it like a 
normal function:

myFunc(10);

Template parameters can be given default values, just like 
function parameters. If all of the template parameters have 
default values or can be inferred, the ! can be omitted in the 
function call.

If you look at the documentation for sort [1], you'll see it's 
declared to take three template arguments. The first two are 
given default values. The last one is not, but since it is the 
type of the function parameter, it can be inferred and not 
specified. So sort *can* be called like this:

sort(myList);

And this will use the default comparison function, the default 
SwapStrategy, and the type of myList will be inferred. If you 
want to change the default comparison function or SwapStrategy, 
you need to use the instantiation operator to specify them. 
That's why it's needed in your example.


>
> 2) Why is a template needed here?

It's not that a template is needed, but that sort is implemented 
as a templated function. I think my answer to number 1 should 
clear this one up, too.


>
> 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?

There are a few different kinds of template parameters [2]. Types 
are perhaps the most common, but there are also template value 
parameters (any compile-time constant), template alias parameters 
(which can be any symbol or compile-time constant), and more. In 
the declaration of sort, you can see three kinds in action:

SortedRange!(Range, less)
sort(alias less = "a < b", SwapStrategy ss = 
SwapStrategy.unstable, Range)(Range r)

The first template parameter, less, is an alias parameter. The 
default value is a string literal which can be mixed in. But you 
could also pass a function name, a function literal (lambda), or 
even an object with a compatible opCall implementation (assuming 
the symbol is in the template's scope). The second parameter is a 
value parameter. SwapStrategy is an enum, the values of which are 
known at compile time. Finally, Range is a type. We know this 
because there's no "alias" or type name in front of it -- it's 
just a solitary symbol.

[1] http://dlang.org/phobos/std_algorithm_sorting.html#sort
[2] http://dlang.org/spec/template.html


More information about the Digitalmars-d-learn mailing list