September 22, 2012
I'm trying to test whether a template argument is the type returned by takeExactly, and I haven't been able to sort out the template voodoo required yet. It would be a lot easier if I had a variable to work with, but I just have the type, and the fancy is expression required to pull it off is fancy enough that I haven't been able to sort it out yet. At present, I have this:

import std.range;
import std.stdio;

template Hello(R)
    if(is(R r == U, V, V w, U = typeof(takeExactly(w, 1))))
{
    alias R Hello;
}

void main()
{
    auto str = "hello";
    auto t = takeExactly(str, 3);
    writeln(t);
    Hello!(typeof(t)) h = t;
    writeln(h);
}


I need Hello to instatiate if R is the type returned by takeExactly and fail to instantiate otherwise. At present, the code gives these compilation errors:

q.d(15): Error: template instance Hello!(Result) Hello!(Result) does not match
template declaration Hello(R) if (is(R r == U,V,V w,U =
typeof(takeExactly(w,1))))
q.d(15): Error: Hello!(Result) is used as a type
q.d(16): Error: template std.stdio.writeln does not match any function
template declaration
q.d(16): Error: template std.stdio.writeln(T...) cannot deduce template
function from argument types !()(_error_)

So, clearly I don't have the is expression right, and this is seriously pushing the edge of my knowledge of is expressions. So, any help would be appreciated. Thanks.

- Jonathan M Davis
September 23, 2012
Jonathan M Davis:

> So, clearly I don't have the is expression right, and this is seriously pushing the edge of my knowledge of is expressions.
> So, any help would be appreciated. Thanks.

I have done some tries, but I have failed, I am sorry :-)
The is() syntax is a part of D good to burn on a campfire.
But takeExactly returns a Result struct defined inside it, so it even possible for the is() syntax to work on this inner (hidden?) type? Generally the idea of defining structs inside looks nice, but seems a source for troubles.

Bye,
bearophile
September 23, 2012
On Sunday, September 23, 2012 02:57:36 bearophile wrote:
> Jonathan M Davis:
> > So, clearly I don't have the is expression right, and this is seriously pushing the edge of my knowledge of is expressions. So, any help would be appreciated. Thanks.
> 
> I have done some tries, but I have failed, I am sorry :-)
> The is() syntax is a part of D good to burn on a campfire.

The power that it provides is useful if not outright necessary, but it could definitely use some improvements in the usability camp once you go beyond the basics. But I don't even know how you'd go about designing it so that it was more user friendly.

> But takeExactly returns a Result struct defined inside it, so it even possible for the is() syntax to work on this inner (hidden?) type? Generally the idea of defining structs inside looks nice, but seems a source for troubles.

Yeah. Increasingly, it looks like Voldemort types are a bad idea as nice as they are in principle. But we have yet to reach the point where it's clear that we need to ditch them. We may yet get there though.

- Jonathan M Davis
September 23, 2012
On 09/23/2012 01:54 AM, Jonathan M Davis wrote:
> I'm trying to test whether a template argument is the type returned by
> takeExactly, and I haven't been able to sort out the template voodoo required
> yet.  It would be a lot easier if I had a variable to work with, but I just
> have the type, and the fancy is expression required to pull it off is fancy
> enough that I haven't been able to sort it out yet. At present, I have this:
>
> import std.range;
> import std.stdio;
>
> template Hello(R)
>      if(is(R r == U, V, V w, U = typeof(takeExactly(w, 1))))
> {
>      alias R Hello;
> }
>
> void main()
> {
>      auto str = "hello";
>      auto t = takeExactly(str, 3);
>      writeln(t);
>      Hello!(typeof(t)) h = t;
>      writeln(h);
> }
>
>
> I need Hello to instatiate if R is the type returned by takeExactly and fail
> to instantiate otherwise. At present, the code gives these compilation errors:
>
> q.d(15): Error: template instance Hello!(Result) Hello!(Result) does not match
> template declaration Hello(R) if (is(R r == U,V,V w,U =
> typeof(takeExactly(w,1))))
> q.d(15): Error: Hello!(Result) is used as a type
> q.d(16): Error: template std.stdio.writeln does not match any function
> template declaration
> q.d(16): Error: template std.stdio.writeln(T...) cannot deduce template
> function from argument types !()(_error_)
>
> So, clearly I don't have the is expression right, and this is seriously
> pushing the edge of my knowledge of is expressions. So, any help would be
> appreciated. Thanks.
>
> - Jonathan M Davis
>

import std.range, std.traits;
import std.stdio;
template Hello(R) if(is(typeof(R._input.takeExactly(2)) == R)){
    alias R Hello;
}

void main(){
    auto str = "hello";
    auto t = takeExactly(str, 3);
    writeln(t);
    Hello!(typeof(t)) h = t;
    writeln(h);
}
September 23, 2012
On 9/23/12 8:47 AM, Timon Gehr wrote:
> import std.range, std.traits;
> import std.stdio;
> template Hello(R) if(is(typeof(R._input.takeExactly(2)) == R)){
> alias R Hello;
> }

That's the nicest. Regarding availability of "_input", I meant to make it available systematically as "input" for ranges where the notion makes sense.

Andrei
September 23, 2012
On 09/23/2012 03:48 PM, Andrei Alexandrescu wrote:
> On 9/23/12 8:47 AM, Timon Gehr wrote:
>> import std.range, std.traits;
>> import std.stdio;
>> template Hello(R) if(is(typeof(R._input.takeExactly(2)) == R)){
>>     alias R Hello;
>> }
>
> That's the nicest.

Well, I noticed it is not entirely correct as takeExactly special cases
sliceable inputs. Therefore, the guard also passes for ranges that have
a sliceable member called _input of the same range type. The correct
guard therefore would be:

if(hasSlicing!R || is(typeof(R._input.takeExactly(2)) == R))

or

if(!hasSlicing!R && is(typeof(R._input.takeExactly(2)) == R))

depending on what the goal is.


> Regarding availability of "_input", I meant to make
> it available systematically as "input" for ranges where the notion makes
> sense.
>
> Andrei

This seems to be reasonable.
September 23, 2012
On Saturday, 22 September 2012 at 23:53:28 UTC, Jonathan M Davis wrote:
> I'm trying to test...
> [SNIP]
> - Jonathan M Davis

I *kind of* see what you are doing with U, V, W, but what's wrong with just doing:

----
import std.range;

template Hello(R)
   if(is(typeof(R == typeof(takeExactly(R, 1)))))
{
   alias R Hello;
}

struct S;

void main( ) {
    Hello!(int[]) a; //OK
    Hello!S b;       //FAIL
}
----
?

It seems to work for me..., but I'm not 100% sure there isn't something illegal/unsafe in there.
September 23, 2012
On 09/23/2012 12:02 PM, monarch_dodra wrote:
> On Saturday, 22 September 2012 at 23:53:28 UTC, Jonathan M Davis wrote:
>> I'm trying to test...
>> [SNIP]
>> - Jonathan M Davis
>
> I *kind of* see what you are doing with U, V, W, but what's wrong with
> just doing:
>
> ----
> import std.range;
>
> template Hello(R)
> if(is(typeof(R == typeof(takeExactly(R, 1)))))
> {
> alias R Hello;
> }
>
> struct S;
>
> void main( ) {
> Hello!(int[]) a; //OK
> Hello!S b; //FAIL
> }
> ----
> ?
>
> It seems to work for me..., but I'm not 100% sure there isn't something
> illegal/unsafe in there.

The goal is to "test whether a template argument is the type returned by takeExactly."

Your solution (I think) is looking at a container and determining whether the type of that container can be compared to the return type of takeExactly(). (Note that typeof(X == Y) is used for checking whether that expression itself is valid.)

Also, I think your code should have passed a range like R.init to takeExactly, not R, which is a type:

  takeExactly(R.init, 1)

I don't know why your code compiles.

Ali
September 23, 2012
On Sunday, 23 September 2012 at 20:56:42 UTC, Ali Çehreli wrote:
> On 09/23/2012 12:02 PM, monarch_dodra wrote:
> > On Saturday, 22 September 2012 at 23:53:28 UTC, Jonathan M
> Davis wrote:
> >> I'm trying to test...
> >> [SNIP]
> >> - Jonathan M Davis
> >
> > I *kind of* see what you are doing with U, V, W, but what's
> wrong with
> > just doing:
> >
> > ----
> > import std.range;
> >
> > template Hello(R)
> > if(is(typeof(R == typeof(takeExactly(R, 1)))))
> > {
> > alias R Hello;
> > }
> >
> > struct S;
> >
> > void main( ) {
> > Hello!(int[]) a; //OK
> > Hello!S b; //FAIL
> > }
> > ----
> > ?
> >
> > It seems to work for me..., but I'm not 100% sure there isn't
> something
> > illegal/unsafe in there.
>
> The goal is to "test whether a template argument is the type returned by takeExactly."
>
> Your solution (I think) is looking at a container and determining whether the type of that container can be compared to the return type of takeExactly(). (Note that typeof(X == Y) is used for checking whether that expression itself is valid.)

Good point. My bad then.

> Also, I think your code should have passed a range like R.init to takeExactly, not R, which is a type:
>
>   takeExactly(R.init, 1)
>
> I don't know why your code compiles.

That did seem fishy to me too actually, but it does compile.

> Ali

In that case, what about:

--------
import std.range;

template Hello(R)
    if(is(typeof(takeExactly(R.init, 1))) && is(R ==
typeof(takeExactly(R.init, 1))))
{
    alias R Hello;
}

struct S{};

void main( ) {
     Hello!(int[]) a; //OK
     Hello!S b;       //FAIL (again)
}
-------
September 23, 2012
On 09/23/2012 10:57 PM, Ali Çehreli wrote:
> ...
>
> Also, I think your code should have passed a range like R.init to
> takeExactly, not R, which is a type:
>
>    takeExactly(R.init, 1)
>
> I don't know why your code compiles.
>

See discussion here:
http://d.puremagic.com/issues/show_bug.cgi?id=8220

« First   ‹ Prev
1 2 3
Top | Discussion index | About this forum | D home