Re: Can't understand templates

2014-11-29 Thread Sly via Digitalmars-d-learn

OK. I'm using gdc 4.8.2 and this doesn't compile, so it's
probably an old version. Checked on ideone and it works with
dmd-2.042.
Thanks a lot for your help!

On Saturday, 29 November 2014 at 20:16:24 UTC, Ali Çehreli wrote:

On 11/29/2014 10:19 AM, Sly wrote:

> You miss another definition which introduces a conflict:
> T getResponse(T)(string question)
> {...}

The following works with dmd git head:

import std.stdio;

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

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

return response;
}

class Pair(A, B) {
  A a;
  B b;
  this(A a, B b) {this.a = a; this.b = b;}
}

Pair!(A, B) getResponse(P : Pair!(A, B), A, B)(string question)
{
writeln(question);
 auto a = getResponse!A(" a");
 auto b = getResponse!B(" b");
 return new Pair!(A, B)(a, b);
}

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

Point!T getResponse(P : Point!T, 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);
}

void main()
{
auto number = getResponse!int("number?");
writeln(number);

auto pair = getResponse!(Pair!(int, long))("pair?");
writeln(pair);

auto point = getResponse!(Point!int)("point?");
writeln(point);
}

Ali


Re: Can't understand templates

2014-11-29 Thread Ali Çehreli via Digitalmars-d-learn

On 11/29/2014 10:19 AM, Sly wrote:

> You miss another definition which introduces a conflict:
> T getResponse(T)(string question)
> {...}

The following works with dmd git head:

import std.stdio;

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

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

return response;
}

class Pair(A, B) {
  A a;
  B b;
  this(A a, B b) {this.a = a; this.b = b;}
}

Pair!(A, B) getResponse(P : Pair!(A, B), A, B)(string question)
{
writeln(question);
 auto a = getResponse!A(" a");
 auto b = getResponse!B(" b");
 return new Pair!(A, B)(a, b);
}

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

Point!T getResponse(P : Point!T, 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);
}

void main()
{
auto number = getResponse!int("number?");
writeln(number);

auto pair = getResponse!(Pair!(int, long))("pair?");
writeln(pair);

auto point = getResponse!(Point!int)("point?");
writeln(point);
}

Ali



Re: Can't understand templates

2014-11-29 Thread Sly via Digitalmars-d-learn

This is clearly an incorrect way because it requires editing the
original definition every time a new class is introduced.

On Saturday, 29 November 2014 at 19:10:34 UTC, Meta wrote:

On Saturday, 29 November 2014 at 18:19:40 UTC, Sly wrote:

You miss another definition which introduces a conflict:
T getResponse(T)(string question)
{...}


In that case, you're better off with a pair of declarations:

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

T getResponse(T)(string message)
if (!is(T == Point!U, U))
{
return T.init;
}

Point!T getResponse(T)(string message)
if (is(T == Point!U, U))
{
return Point!T(T.init, T.init);
}

void main()
{
auto t = getResponse!int("test");
auto p = getResponse!(Point!int)("test");
}


Re: Can't understand templates

2014-11-29 Thread Meta via Digitalmars-d-learn

On Saturday, 29 November 2014 at 18:19:40 UTC, Sly wrote:

You miss another definition which introduces a conflict:
T getResponse(T)(string question)
{...}


In that case, you're better off with a pair of declarations:

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

T getResponse(T)(string message)
if (!is(T == Point!U, U))
{
return T.init;
}

Point!T getResponse(T)(string message)
if (is(T == Point!U, U))
{
return Point!T(T.init, T.init);
}

void main()
{
auto t = getResponse!int("test");
auto p = getResponse!(Point!int)("test");
}


Re: Can't understand templates

2014-11-29 Thread Sly via Digitalmars-d-learn

You miss another definition which introduces a conflict:
T getResponse(T)(string question)
{...}

On Saturday, 29 November 2014 at 17:20:42 UTC, Meta wrote:

On Saturday, 29 November 2014 at 11:07:34 UTC, Sly wrote:
On Saturday, 29 November 2014 at 09:11:51 UTC, Ali Çehreli 
wrote:



Point!T getResponse(P : Point!T, T)(string question)
{
  // ...
}



This doesn't work because now this definition has 2 parameters 
P

and T. I have to specify both like this: auto pt =
getResponse!(Point!int, int)("point");  which of course defeats
the purpose. Otherwise I have ambiguity error:


Not true, T is inferred based on the the type Point has been 
instantiated with, letting you emit the second template 
argument. The following code works:


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

P getResponse(P: Point!T, T)(string message)
{
return P(T.init, T.init);
}

void main()
{
import std.stdio;

//T is inferred to be int automatically
writeln(getResponse!(Point!int)("test"));
}


Re: Can't understand templates

2014-11-29 Thread Meta via Digitalmars-d-learn

On Saturday, 29 November 2014 at 11:07:34 UTC, Sly wrote:
On Saturday, 29 November 2014 at 09:11:51 UTC, Ali Çehreli 
wrote:



Point!T getResponse(P : Point!T, T)(string question)
{
   // ...
}



This doesn't work because now this definition has 2 parameters P
and T. I have to specify both like this: auto pt =
getResponse!(Point!int, int)("point");  which of course defeats
the purpose. Otherwise I have ambiguity error:


Not true, T is inferred based on the the type Point has been 
instantiated with, letting you emit the second template argument. 
The following code works:


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

P getResponse(P: Point!T, T)(string message)
{
return P(T.init, T.init);
}

void main()
{
import std.stdio;

//T is inferred to be int automatically
writeln(getResponse!(Point!int)("test"));
}


Re: Can't understand templates

2014-11-29 Thread Sly via Digitalmars-d-learn

On Saturday, 29 November 2014 at 09:11:51 UTC, Ali Çehreli wrote:


Point!T getResponse(P : Point!T, T)(string question)
{
// ...
}



This doesn't work because now this definition has 2 parameters P
and T. I have to specify both like this: auto pt =
getResponse!(Point!int, int)("point");  which of course defeats
the purpose. Otherwise I have ambiguity error:

d.d:73: error: d.getResponse called with argument types (string)
matches both:
d.d(20): getResponse(T)(string question)
and:
d.d(31): getResponse(P : Point!T, T)(string question)

Same thing with specialization for Pair.


Actually what I wrote earlier about C++ is wrong because C++
doesn't allow partial specialization for functions. I wrote this
example in C++ using classes:


template
struct Reader {
 static T getResponse(const std::string& question) {
 std::cout << question << "(" << typeid(T).name() << "): 
";

 T res;
 std::cin >> res;
 return res;
 }
};

template
struct Point {
 T x, y;
};

template
struct Reader> {
 static Point getResponse(const std::string& question) {
 std::cout << question << "\n";
 Point res;
 res.x = Reader::getResponse(" x");
 res.y = Reader::getResponse(" y");
 return res;
 }
};

template
struct Reader> {
 static std::pair getResponse(const std::string&
question) {
 std::cout << question << "\n";
 std::pair res;
 res.first = Reader::getResponse(" first");
 res.second = Reader::getResponse(" second");
 return res;
 }
};


int main()
{
 int i = Reader::getResponse("int");
 auto pt = Reader>::getResponse("point");
 auto pair = Reader>::getResponse("pair");

 return 0;
}



I translated it literally into D using your syntax and it worked!


class Reader(T) {
 public static T getResponse(string question) {
 writef("%s (%s): ", question, T.stringof);
 T response;
 readf(" %s", &response);
 return response;
 }
}

class Reader(P: Point!T, T) {
 public static Point!T getResponse(string question) {
 writefln("%s (Point!%s)", question, T.stringof);
 auto x = Reader!T.getResponse(" x");
 auto y = Reader!T.getResponse(" y");
 return Point!T(x, y);
 }
}

class Reader(P: Pair!(A, B), A, B) {
 public static Pair!(A, B) getResponse(string question) {
 writefln("%s (Pair!(%s, %s))", question, A.stringof,
B.stringof);
 auto a = Reader!A.getResponse(" a");
 auto b = Reader!B.getResponse(" b");
 return new Pair!(A, B)(a, b);
 }
}

void main()
{
 auto i = Reader!int.getResponse("int");
 auto pt = Reader!(Point!int).getResponse("point");
 auto pair = Reader!(Pair!(int, int)).getResponse("pair");
}


My questions now are:

1. Apparently D has partial specializations of function
templates, but it uses a weird syntax (T: Point!T). How to extend
this syntax for multiple template parameters? (Basically, how to
write this example without wrapping the function into a class?)

2. Why is there a difference between partial specialization of
function templates and class templates: there's a compilation
error with function templates but not with class templates?


Re: Can't understand templates

2014-11-29 Thread Ali Çehreli via Digitalmars-d-learn

On 11/29/2014 12:41 AM, Sly wrote:

Ah, now I see. In C++ we would also need to supply template
parameters, but we'd put them before return type
(template getResponse>); in D we put them
before the colon.

Now I'm trying to write a specialization for Pair. It seems that
this is the way to do it:

Pair!(A, B) getResponse(A, B: Pair!(A, B))(string question)
{
  auto a = getResponse!A(" a");
  auto b = getResponse!B(" b");
  return new Pair!(A, B)(a, b);
}

auto pair = getResponse!(Pair!(int, int))("pair?");

But it doesn't work: this call resolves to a general version T
getResponse(T), and I get a compilation error because it tries to
instantiate readf!(Pair*).
What am I doing wrong?


I wish I could formalize these definitions better or consistently but 
here my "art", which works: :)


Pair!(A, B) getResponse(P : Pair!(A, B), A, B)(string question)
{
// ...
}

That template parameter reads:

- This template takes a single parameter (P)

- P must match Pair!(A, B)

- Where A and B are both types

So, getting back to Point, now the following is consistent with the above:

Point!T getResponse(P : Point!T, T)(string question)
{
// ...
}

Now, that means: "This is a specialization for P, where it matches 
Point!T and T is a type."


Maybe I should change the specialization examples in that chapter...

Ali



Re: Can't understand templates

2014-11-29 Thread Sly via Digitalmars-d-learn

Ah, now I see. In C++ we would also need to supply template
parameters, but we'd put them before return type
(template getResponse>); in D we put them
before the colon.

Now I'm trying to write a specialization for Pair. It seems that
this is the way to do it:

Pair!(A, B) getResponse(A, B: Pair!(A, B))(string question)
{
 auto a = getResponse!A(" a");
 auto b = getResponse!B(" b");
 return new Pair!(A, B)(a, b);
}

auto pair = getResponse!(Pair!(int, int))("pair?");

But it doesn't work: this call resolves to a general version T
getResponse(T), and I get a compilation error because it tries to
instantiate readf!(Pair*).
What am I doing wrong?

On Saturday, 29 November 2014 at 08:06:33 UTC, Ali Çehreli wrote:

On 11/28/2014 10:26 PM, Sly wrote:

> I still don't understand how to
> read this signature:
> Point!T getResponse(T: Point!T)(string question)

The following is what makes sense to me.

Sorry for going step by step but I think it helped me 
understand your question. (See item 3 below.)


1) Point!T is the return type. Although T is unknown at this 
point, we will wait a little because it may be a template 
parameter.


Also, according to the syntax of Point!T, Point is apparently a 
template. So, this function will return the T instantiation of 
Point, whatever T will be deduced to be in a moment.


2) getResponse is the name of the function

3) The first set of parameters is the template parameters:

(T: Point!T)

The meaning: T is a type and this specialization is for Point!T.

Ok, I think I finally understand your original question. I 
agree that it doesn't make sense to say "T is a type and this 
specialization is for Point!T". I think we need to read it 
backward in this case: "This specialization is for Point!T. If 
so, deduce T from that." So, if getResponse is instantiated 
with Point!int, then T is deduced to be int.


4) The instances of this function template take string 
parameter.


Ali


Re: Can't understand templates

2014-11-29 Thread Ali Çehreli via Digitalmars-d-learn

On 11/28/2014 10:26 PM, Sly wrote:

> I still don't understand how to
> read this signature:
> Point!T getResponse(T: Point!T)(string question)

The following is what makes sense to me.

Sorry for going step by step but I think it helped me understand your 
question. (See item 3 below.)


1) Point!T is the return type. Although T is unknown at this point, we 
will wait a little because it may be a template parameter.


Also, according to the syntax of Point!T, Point is apparently a 
template. So, this function will return the T instantiation of Point, 
whatever T will be deduced to be in a moment.


2) getResponse is the name of the function

3) The first set of parameters is the template parameters:

(T: Point!T)

The meaning: T is a type and this specialization is for Point!T.

Ok, I think I finally understand your original question. I agree that it 
doesn't make sense to say "T is a type and this specialization is for 
Point!T". I think we need to read it backward in this case: "This 
specialization is for Point!T. If so, deduce T from that." So, if 
getResponse is instantiated with Point!int, then T is deduced to be int.


4) The instances of this function template take string parameter.

Ali



Re: Can't understand templates

2014-11-28 Thread Sly via Digitalmars-d-learn

OK, so we *can* have overlapping templates in one fits better
than another, just like in C++. I still don't understand how to
read this signature:
Point!T getResponse(T: Point!T)(string question)


On Friday, 28 November 2014 at 23:59:07 UTC, Ali Çehreli wrote:

On 11/28/2014 12:36 PM, Sly wrote:

> Let's take a simpler example from earlier in the tutorial,
where
> Point is a non-template struct:
>
>
> // The general definition of the function template (same as
> before)
> T getResponse(T)(string question)
> {
[...]
> }

That definition would work with any type T. So, it is general: 
it accepts any type.


> // The specialization of the function template for Point
> T getResponse(T : Point)(string question)
> {
[...]
> }

That definition is for T that matches Point (i.e. Point itself 
in this example). So, it is special: it accepts only that type.


> auto center = getResponse!Point("Where is the center?");
>
> Doesn't getResponse!Point match both declarations?

True but the call is dispatched to the most special of all of 
the matches. It is very briefly explained through a reference 
to C++:


"The template picked to instantiate is the one that is most 
specialized that fits the types of the TemplateArgumentList. 
Determine which is more specialized is done the same way as the 
C++ partial ordering rules. If the result is ambiguous, it is 
an error."


See the "Specialization" heading here:

  http://dlang.org/template.html

Ali


Re: Can't understand templates

2014-11-28 Thread Ali Çehreli via Digitalmars-d-learn

On 11/28/2014 12:36 PM, Sly wrote:

> Let's take a simpler example from earlier in the tutorial, where
> Point is a non-template struct:
>
>
> // The general definition of the function template (same as
> before)
> T getResponse(T)(string question)
> {
[...]
> }

That definition would work with any type T. So, it is general: it 
accepts any type.


> // The specialization of the function template for Point
> T getResponse(T : Point)(string question)
> {
[...]
> }

That definition is for T that matches Point (i.e. Point itself in this 
example). So, it is special: it accepts only that type.


> auto center = getResponse!Point("Where is the center?");
>
> Doesn't getResponse!Point match both declarations?

True but the call is dispatched to the most special of all of the 
matches. It is very briefly explained through a reference to C++:


"The template picked to instantiate is the one that is most specialized 
that fits the types of the TemplateArgumentList. Determine which is more 
specialized is done the same way as the C++ partial ordering rules. If 
the result is ambiguous, it is an error."


See the "Specialization" heading here:

  http://dlang.org/template.html

Ali



Re: Can't understand templates

2014-11-28 Thread Sly via Digitalmars-d-learn

On Friday, 28 November 2014 at 19:45:48 UTC, H. S. Teoh via
Digitalmars-d-learn wrote:

This syntax is a little confusing, but basically the ":" there 
is saying
"this type, when instantiated with the following pattern, 
produces a

valid type". Essentially it's equivalent to:

Point!T getResponse(T)(string question)
if (is(typeof(Point!T))) // i.e., Point!T is a valid type
{
...
}



Is there a typo here? This version doesn't compile with the
original call: auto pt = getResponse!(Point!int)("point");



Yes, because D does not support overlapping template overloads.


But I thought the original example has ovelapping templates.
Let's take a simpler example from earlier in the tutorial, where
Point is a non-template struct:


// The general definition of the function template (same as
before)
T getResponse(T)(string question)
{
 writef("%s (%s): ", question, T.stringof);

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

 return response;
}

// The specialization of the function template for Point
T getResponse(T : Point)(string question)
{
 writefln("%s (Point)", question);

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

 return Point(x, y);
}

auto center = getResponse!Point("Where is the center?");

Doesn't getResponse!Point match both declarations?


Re: Can't understand templates

2014-11-28 Thread H. S. Teoh via Digitalmars-d-learn
On Fri, Nov 28, 2014 at 07:32:38PM +, Sly via Digitalmars-d-learn wrote:
> Here is an example from the tutorial:
[...]
> 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);
> }
[...]
> I don't understand how to read this signature: Point!T
> getResponse(T: Point!T)(string question). Clearly it's not
> supposed to be saying that T is subclass of Point!T, so those Ts
> must refer to different types. But when I rename it to
> getResponse(U: Point!T) I get a compilation error (unknown
> identifier T).

This syntax is a little confusing, but basically the ":" there is saying
"this type, when instantiated with the following pattern, produces a
valid type". Essentially it's equivalent to:

Point!T getResponse(T)(string question)
if (is(typeof(Point!T))) // i.e., Point!T is a valid type
{
...
}


> Another question: say I have a template class Pair:
> 
> class Pair(A, B) {
>   A a;
>   B b;
>   this(A a, B b) {this.a = a; this.b = b;}
> }
> 
> How to write a specialization for getResponse matching Pair!(A, B)
> with any type arguments A and B? I tried this:
> 
> T getResponse(T)(string question)
>   if (is(T: Pair!(A, B), A, B))
> {
>   auto a = getResponse!A(" a");
>   auto b = getResponse!B(" b");
>   return new Pair!(A, B)(a, b);
> }
> 
> but get a compile error:
> 
> error: d.getResponse called with argument types (string) matches
> both:
>   d.d(19): getResponse(T)(string question)
> and:
>   d.d(40): getResponse(T)(string question) if (is(T : Pair!(A, B),
> A, B))

Yes, because D does not support overlapping template overloads.  Both
the original overload of getResponse and the new overload matches the
given arguments, so it's an error. You need to explicitly restrict the
original overload so that it does *not* match in the case a Pair is
given. For example:

// Original overload
Point!T getResponse(T : Point!T)(string question)
if (!is(T : Pair!(A, B), A, B))
// ^^^ this says, match all T's for which Point!T is a
// valid type, but not when T is also an instantiation
// of Pair!(A,B).
{
...
}

// New overload
T getResponse(T)(string question)
if (is(T : Pair!(A, B), A, B))
{
...
}


T

-- 
It is impossible to make anything foolproof because fools are so ingenious. -- 
Sammy