August 02, 2013
On Friday, 2 August 2013 at 12:37:00 UTC, John Colvin wrote:
> Are all types guaranteed to have a working .init value? I can't think of any way not to, but I just want to be sure.

Not sure what you mean by "working" but there is a hard guarantee that for any type "T.init" will compile and result in some value. That was the key idea behind .init and reason why default constructors are prohibited for structs.
August 02, 2013
On Friday, 2 August 2013 at 12:47:24 UTC, Dicebot wrote:
> On Friday, 2 August 2013 at 12:37:00 UTC, John Colvin wrote:
>> Are all types guaranteed to have a working .init value? I can't think of any way not to, but I just want to be sure.
>
> Not sure what you mean by "working" but there is a hard guarantee that for any type "T.init" will compile and result in some value. That was the key idea behind .init and reason why default constructors are prohibited for structs.

Thanks, that's how I thought it worked.
August 02, 2013
On Friday, 2 August 2013 at 12:37:00 UTC, John Colvin wrote:
> On Friday, 2 August 2013 at 11:26:41 UTC, monarch_dodra wrote:
>> Is this what you want?
>
> Thankyou, yes that's exactly right.
>
> Are all types guaranteed to have a working .init value? I can't think of any way not to, but I just want to be sure.

Yes, but there's a catch: T.init is an RValue, so if you have "foo(ref T)", then:
foo(T.init)
won't compile (and rightly so).

user denis-sh proposed the lvalueOf functionional "trait":
https://github.com/D-Programming-Language/phobos/pull/1261
@property ref T lvalueOf(T)(inout int = 0);

This can be used *only* at compile time (no body, so it won't link), and is meant to be used in constraints/static ifs.

In this case:
static assert(is(typeof(foo(lvalueOf!T))));
*Will* work.
August 02, 2013
On Friday, 2 August 2013 at 11:26:41 UTC, monarch_dodra wrote:
> On Friday, 2 August 2013 at 10:54:06 UTC, John Colvin wrote:
>> On Thursday, 1 August 2013 at 15:08:53 UTC, John Colvin wrote:
>>> On Thursday, 1 August 2013 at 14:57:07 UTC, monarch_dodra wrote:
>>>> On Thursday, 1 August 2013 at 12:50:42 UTC, John Colvin wrote:
>>>>> template a(T ...)
>>>>> {
>>>>> void a(R r)
>>>>> {
>>>>>     //want to get a tuple of
>>>>>     //the members of T, each
>>>>>     //instantiated with R.
>>>>>
>>>>>     //do some RT stuff
>>>>> }
>>>>> }
>>>>>
>>>>> Is this possible?
>>>>>
>>>>> Whatever I try, I keep running in to "cannot use local as parameter to non-global template" errors, which I understand is to do with context pointers
>>>>> However, this is all compile-time work based entirely on types, there should be no need for any context pointers.
>>>>
>>>> Still not sure what you want, but you may want to look into adjoin and  staticMap.
>>>
>>> Sorry, now I've thought about it some more it appears I was asking the wrong question completely!
>>>
>>> Here's the situation (you might recognise the pattern from std.algorithm.map):
>>>
>>> template a(funs...)
>>> {
>>>   auto a(R)(R r)
>>>   {
>>>       alias /*something*/ nonVoidFuns;
>>>       alias /*something*/ voidFuns;
>>>
>>>       //do stuff with nonVoidFuns and voidFuns applied to r
>>>   }
>>> }
>>>
>>> so i need to find the return type of each fun, when called with something of type R (bearing in mind that fun!R may not be the same type as fun(r) as fun might be T fun(T)(T[] a), then filter funs to seperate the void functions from the non-void ones. Or something else to that effect.
>>>
>>> I've tried several things with std.typetuple.Filter but nothing seems to work.
>>
>> Any ideas anyone? It seems like something that should be easily done somehow.
>
> //----
> import std.stdio, std.typetuple;
>
> template isVoidArg(U)
> {
>     template isVoid(alias F)
>     {
>         enum isVoid = is(typeof(F(U.init)) == void);
>     }
>     alias isVoidArg = isVoid;
> }
> template isNonVoidArg(U)
> {
>     template isNonVoid(alias F)
>     {
>         enum isNonVoid = is(typeof({auto a = F(U.init);}));
>     }
>     alias isNonVoidArg = isNonVoid;
> }
> template isErrorArg(U)
> {
>     template isError(alias F)
>     {
>         enum isError = !is(typeof(F(U.init)));
>     }
>     alias isErrorArg = isError;
> }
>
> template a(funs...)
> {
>    auto a(R)(R r)
>    {
>       alias nonVoidFuns = Filter!(isNonVoidArg!R, funs);
>       alias voidFuns = Filter!(isVoidArg!R, funs);
>       alias voidErrorFuns = Filter!(isErrorArg!R, funs);
>
>       import std.functional : adjoin;
>
>       writeln("Calling all non voids!");
>       adjoin!nonVoidFuns(r);
>       writeln("Calling all voids!");
>       adjoin!voidFuns(r);
>    }
> }
>
> void fun1(string i)
> {
>     writeln("fun1 ", i);
> }
> int fun2()
> {
>     writeln("fun2");
>     return int.min;
> }
> void fun3(int i)
> {
>     writeln("fun3 ", i);
> }
> int fun4(int i)
> {
>     writeln("fun4 ", i);
>     return i;
> }
>
> void main()
> {
>     a!(fun1, fun2, fun3, fun4)(99);
> }
> //----
> Calling all non voids!
> fun4 5
> Calling all voids!
> fun3 5
> //----
>
> Is this what you want?

I just ran in to a problem with this. It can't work for anything other than global functions.

void main()
{	
    int fun6(int i)
    {
        writeln("fun6 ", i);
        return i;
    }
    a!(fun6)(99);
}

std/typetuple.d(664): Error: template instance pred!(fun6) cannot use local 'fun6' as parameter to non-global template isVoidFun(alias fun)

So it's back to that same problem again.
August 02, 2013
On Friday, 2 August 2013 at 12:58:08 UTC, John Colvin wrote:
> std/typetuple.d(664): Error: template instance pred!(fun6) cannot use local 'fun6' as parameter to non-global template isVoidFun(alias fun)
>
> So it's back to that same problem again.

That is probably my most hated error message ever... Anyway, it should work if "isVoidFun" is global (not nested) symbol, not "fun6". Are you sure about it?
August 02, 2013
On Friday, 2 August 2013 at 12:58:08 UTC, John Colvin wrote:
>> Is this what you want?
>
> I just ran in to a problem with this. It can't work for anything other than global functions.
>
> void main()
> {	
>     int fun6(int i)
>     {
>         writeln("fun6 ", i);
>         return i;
>     }
>     a!(fun6)(99);
> }
>
> std/typetuple.d(664): Error: template instance pred!(fun6) cannot use local 'fun6' as parameter to non-global template isVoidFun(alias fun)
>
> So it's back to that same problem again.

The "root" problem is that filter just isn't adapted here. If you don't mind writing "filter 2 (for example)" though...

//--------
import std.stdio, std.typetuple;

template isVoidArg(alias F, U)
{
    enum isVoidArg = is(typeof(F(U.init)) == void);
}
template isNonVoidArg(alias F, U)
{
    enum isNonVoidArg = is(typeof({auto a = F(U.init);}));
}
template isErrorArg(alias F, U)
{
    enum isErrorArg = !is(typeof(F(U.init)));
}

template Filter2(alias pred, U, TList...)
{
    static if (TList.length == 0)
    {
        alias Filter2 = TypeTuple!();
    }
    else static if (TList.length == 1)
    {
        static if (pred!(TList[0], U))
            alias Filter2 = TypeTuple!(TList[0]);
        else
            alias Filter2 = TypeTuple!();
    }
    else
    {
        alias Filter2 =
            TypeTuple!(
                Filter2!(pred, U, TList[ 0  .. $/2]),
                Filter2!(pred, U, TList[$/2 ..  $ ]));
    }
}

template a(funs...)
{
   auto a(R)(R r)
   {
      alias nonVoidFuns = Filter2!(isNonVoidArg, R, funs);
      alias voidFuns = Filter2!(isVoidArg, R, funs);
      alias voidErrorFuns = Filter2!(isErrorArg, R, funs);

      import std.functional : adjoin;

      writeln("Calling all non voids!");
      adjoin!nonVoidFuns(r);
      writeln("Calling all voids!");
      adjoin!voidFuns(r);
   }
}

void main()
{
    void fun1(string i)
    {
        writeln("fun1 ", i);
    }
    int fun2()
    {
        writeln("fun2");
        return int.min;
    }
    void fun3(int i)
    {
        writeln("fun3 ", i);
    }
    int fun4(int i)
    {
        writeln("fun4 ", i);
        return i;
    }

    a!(fun1, fun2, fun3, fun4)(99);
}
//--------

The template names kind of suck though. You may want to change some of them.
August 02, 2013
On Friday, 2 August 2013 at 13:07:16 UTC, Dicebot wrote:
> On Friday, 2 August 2013 at 12:58:08 UTC, John Colvin wrote:
>> std/typetuple.d(664): Error: template instance pred!(fun6) cannot use local 'fun6' as parameter to non-global template isVoidFun(alias fun)
>>
>> So it's back to that same problem again.
>
> That is probably my most hated error message ever... Anyway, it should work if "isVoidFun" is global (not nested) symbol, not "fun6". Are you sure about it?

I'd made some changes before getting that error. Using monarch_dodra's code verbatim:

void main()
{
	void fun1(string i)
	{
		writeln("fun1 ", i);
	}
	
	a!(fun1)(99);
}

std/typetuple.d(664): Error: template instance pred!(fun1) cannot use local 'fun1' as parameter to non-global template isNonVoid(alias F)
and a whole load more crap
1 2
Next ›   Last »