August 09, 2022

On Tuesday, 2 August 2022 at 12:39:41 UTC, pascal111 wrote:

>

On Tuesday, 2 August 2022 at 04:06:30 UTC, frame wrote:

>

On Monday, 1 August 2022 at 23:35:13 UTC, pascal111 wrote:

>

This is the definition of "filter" function, and I think it called itself within its definition. I'm guessing how it works?

It's a template that defines the function called "Eponymous Templates":
https://dlang.org/spec/template.html#implicit_template_properties

A template generates code, it cannot be called, only instantiated.

The common syntax is just a shortcut for using it. Otherwise you would need to write filter!(a => a > 0).filter([1, -1, 2, 0, -3]). Like UFCS, some magic the compiler does for you.

Instantiation seems some complicated to me. I read "If a template contains members whose name is the same as the template identifier then these members are assumed to be referred to in a template instantiation:" in the provided link, but I'm still stuck. Do you have a down-to-earth example for beginners to understand this concept?

A template is conceptually like a macro with parameters in C. An instantiation is like the using of the macro in your C program. The fundamental difference is, that the template is syntactically and semantically linked to the language. In C, the preprocessor was just a textual replacement done before the proper compilation. This meant that there are things that you couldn't do in the pre-processor (like #if sizeof(int)==4) and (horrible) things that never should have been possible (I used to use the C pre-processor with other languages like AutoLISP and dBase III).

August 09, 2022

On Monday, 1 August 2022 at 23:35:13 UTC, pascal111 wrote:

>

This is the definition of "filter" function, and I think it called itself within its definition. I'm guessing how it works?

'''D
template filter(alias predicate)
if (is(typeof(unaryFun!predicate)))
{
/**
Params:
range = An $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
of elements
Returns:
A range containing only elements x in range for
which predicate(x) returns true.
*/
auto filter(Range)(Range range) if (isInputRange!(Unqual!Range))
{
return FilterResult!(unaryFun!predicate, Range)(range);
}
}
'''

I think this line needs explanation:

'''D
return FilterResult!(unaryFun!predicate, Range)(range);
'''

To give a vastly simplified answer, the term "eponymous template" essentially means that if you have an item declared inside a template that has a same name as the template:

template SomeTemplate(T)
{
    alias SomeTemplate = T;
}

It is not a compile error. Instead, when you use the template:

SomeTemplate!int n;

The compiler rewrites your code like to:

SomeTemplate!int.SomeTemplate n;

Because normally when you instantiate a template, you have to refer to the declarations inside it by name:

template SomeOtherTemplate(T)
{
    alias SomeAlias = T;
}

//SomeOtherTemplate!int n; Error: `SomeOtherTemplate!int` is used as a type
SomeOtherTemplate!int.SomeAlias n; //Ok

Except in the special case I outlined above. It's essentially a hack that was brought over from C++. It makes using templates more ergonomic.

August 15, 2022

On Tuesday, 2 August 2022 at 12:39:41 UTC, pascal111 wrote:

>

but I'm still stuck. Do you have a down-to-earth example for beginners to understand this concept?

I often go back to this post when writing templates:

https://dlang.org/blog/2020/07/31/the-abcs-of-templates-in-d/

It helped me when I was first trying to understand them.

1 2
Next ›   Last »