April 09, 2019
On Tuesday, 9 April 2019 at 14:41:30 UTC, Alex wrote:

> Your confusion arises in your understanding of meta programming and templates. Templates are compile time expressions that use parameters.

This sounds like another 'no.' :)

Thanks for all the info, Alex.
April 09, 2019
On 4/9/19 4:31 PM, Ron Tarrant wrote:

> I'm still struggling to understand templates, but I'll keep at it.

When I first saw C++ templates, I thought "what the hell is this black magic", and had no idea how they worked. In fact, this was back before STL, and I recall it was a set of templates called "Rogue Wave". None of us who were working on the project at the time understood them, so we ripped them all out.

The thing that made it click for me is that a template is very akin to a macro substitution -- where you just copy and paste the given parameter wherever its substitute is found.

For example:

struct S(T)
{
   T member;
}

S!int => put int wherever you see T.

So it's like you typed:

struct S
{
   int member;
}

and that's what the compiler sees. All optimization, layout, etc. works exactly like you typed that directly. But instead of creating one type for every member type you need, you just write it once and "instantiate" the template giving the type you want.

I will say, it's not EXACTLY the same as macro substitution -- there are rules. But it's a good way to think about it. I actually am going to go over this kind of thinking a bit in my talk this year at dconf.

-Steve
April 09, 2019
On Tue, Apr 09, 2019 at 04:48:45PM -0400, Steven Schveighoffer via Digitalmars-d-learn wrote:
> On 4/9/19 4:31 PM, Ron Tarrant wrote:
> 
> > I'm still struggling to understand templates, but I'll keep at it.
[...]
> The thing that made it click for me is that a template is very akin to a macro substitution -- where you just copy and paste the given parameter wherever its substitute is found.
[...]

Yes, templates are, functionally speaking, macros with type safety, and in D's case syntactic sanity, and none of the disadvantages of an actual macro system.


T

-- 
Heads I win, tails you lose.
April 09, 2019
On 04/08/2019 05:23 AM, Ron Tarrant wrote:

> But in "Programming in D," (self, 2009-2018) by Ali Çehreli, there's no
> mention of the 'template' keyword in any of his examples.

'template' keyword is introduced here:

  http://ddili.org/ders/d.en/templates_more.html#ix_templates_more.template

I found that page by clicking on one of the two 'template' entries under T in the book's index:

  http://ddili.org/ders/d.en/ix.html

Ali

April 09, 2019
On 04/08/2019 05:59 AM, Ron Tarrant wrote:
> On Monday, 8 April 2019 at 12:40:10 UTC, Adam D. Ruppe wrote:
> 
>> You don't need template keyword for the majority of cases because the compiler lets you do shortcuts.
> Thanks, Adam. Good to know.
> 
> 
>> (maybe I am looking at the wrong part of the book, it is hard to find the right section/page number online).
> 
> My bad. The edition I'm working from was released 2018-10-17 and can be found here:
> 
> http://ddili.org/ders/d.en/Programming_in_D.pdf
> 
> The page number in online PDF viewer is 421 and the example is about 1/3 of the way down the page.
> 
>
That template specialization works along with the general definition of the same template. So, you must have the following function template as well:

T getResponse(T)(string question) {
    writef("%s (%s): ", question, T.stringof);

    T response;
    readf(" %s", &response);

    return response;
}

As Steve said, when you replace all Ts in there e.g. with int, you get what the compiler would generate for T being int. However, the readf above cannot work with e.g. Point!double because readf does not know what Point!double is. For that reason, we may use a specialization for Point!T:

Point!T getResponse(T : Point!T)(string question)
{
    writefln("%s (Point!%s)", question, T.stringof);

    auto x = getResponse!T(" x");
    auto y = getResponse!T(" y");

    return(Point!T(x, y));

} // getResponse() Point!T

(It may be made to work with Adam's (T : Point!R, R) syntax but I failed just now.)

Now you have a specialization that works with any Point!T. T can be double, int, etc. However, you must call getResponse with that special Point. I'm using an alias for code reduction:

  alias MapLocation = Point!double;
  auto wayPoint1 = getResponse!MapLocation("Where is the first map location?");
  auto wayPoint2 = getResponse!MapLocation("Where is the second map location?");

Your code did not work because Point is not a type but a type template. (On the other hand, Point!double is a type). The whole program:

import std.stdio;
import std.math;
import std.string;

struct Point(T)
{
    T x;
    T y;

    T distanceTo(Point that) const
    {
        immutable real xDistance = x - that.x;
        immutable real yDistance = y - that.y;

        immutable distance = sqrt((xDistance * xDistance) + (yDistance * yDistance));

        return(cast(T)distance);

    } // distanceTo()

} // struct Point

T getResponse(T)(string question) {
    writef("%s (%s): ", question, T.stringof);

    T response;
    readf(" %s", &response);

    return response;
}

Point!T getResponse(T : Point!T)(string question)
{
    writefln("%s (Point!%s)", question, T.stringof);

    auto x = getResponse!T(" x");
    auto y = getResponse!T(" y");

    return(Point!T(x, y));

} // getResponse() Point!T


void main()
{
  alias MapLocation = Point!double;
    auto wayPoint1 = getResponse!MapLocation("Where is the first map location?");
    auto wayPoint2 = getResponse!MapLocation("Where is the second map location?");

    writeln("Distance: ", wayPoint1.distanceTo(wayPoint2));

} // main()

Ali
April 10, 2019
On Wednesday, 10 April 2019 at 00:42:11 UTC, Ali Çehreli wrote:
> (It may be made to work with Adam's (T : Point!R, R) syntax but I failed just now.)

You know, I didn't think T : Point!T would work, but it does. Huh.

Anyway, the , R one works similarly, observe:

---
T getResponse(T : Point!R, R)(string question) {
    writef("%s (%s): ", question, T.stringof);

    R response;
    readf(" %s", &response);

    return T(response);
}
---

In this case, when you pass it a Point!double, T is still the full type, Point!double (so the return value there needs to be constructed), but R is now just the `double` part, so we can pass that independently to readf.

This pattern is also useful for capturing static arrays:


void processStaticArray(A : T[N], T, size_t N)(ref A) {
	writeln(T.stringof, " ", N);
}

void main()
{
    int[5] arr;
    processStaticArray(arr);
}


There, A is our static array type, but then we deconstruct its pieces to get the size and inner type too. This lets us pass any static array in without losing the compile-time length.

(though usually I'd just slice it and call it T[]!)



These patterns are also used by the `is` expression, and you can rename the whole thing there when used inside `static if`. (I know most people think this is crazy black magic, but it actually isn't that crazy once you know the pattern - write the symbol with placeholders, add a comma, define the placeholders. Then the other forms like is(T == X) and is(T : X) and even is(T N == X) are just optional additions to this - == means is equal to, : means can convert to, and the N in the last one renames the value extracted to something else, most valuable in is(typeof(func) Params == __parameters).

So yeah, there is a bit to it, but it is just a pattern, condition, optional placeholders, optional rename.)
April 10, 2019
On Tuesday, 9 April 2019 at 20:48:45 UTC, Steven Schveighoffer wrote:

> The thing that made it click for me is that a template is very akin to a macro substitution -- where you just copy and paste the given parameter wherever its substitute is found.

Nicely put. Thanks, Steve. I at least get the basics now.


April 10, 2019
On Wednesday, 10 April 2019 at 00:22:47 UTC, Ali Çehreli wrote:
> On 04/08/2019 05:23 AM, Ron Tarrant wrote:
>
> > But in "Programming in D," (self, 2009-2018) by Ali Çehreli,
> there's no
> > mention of the 'template' keyword in any of his examples.
>
> 'template' keyword is introduced here:
>
>   http://ddili.org/ders/d.en/templates_more.html#ix_templates_more.template
>
> I found that page by clicking on one of the two 'template' entries under T in the book's index:
>
>   http://ddili.org/ders/d.en/ix.html
>
> Ali

Oops! Sorry, Ali. Since the advent of PDF, I rarely think to look in a book's index. I shall go blush now.

And apologies for making such a blanket statement about not mentioning the template keyword. I've learned a lot from your book and I don't want to create the impression I haven't.

April 10, 2019
On Wednesday, 10 April 2019 at 00:42:11 UTC, Ali Çehreli wrote:
> Your code did not work because Point is not a type but a type template. (On the other hand, Point!double is a type). The whole program:

Thanks very much, Ali! Obviously, I've got some studying ahead of me.
April 10, 2019
On 04/10/2019 05:07 AM, Ron Tarrant wrote:

>> the book's index:
>>
>>   http://ddili.org/ders/d.en/ix.html

> Oops!

Not at all. One of the most useful parts of the book has been the index section for me. I occasionally search in there... like just yesterday for the positional format specifier %1$. :)

Ali

1 2
Next ›   Last »