March 13, 2008
I am trying to write a small function that returns the first nonzero argument. For 2 arguments the following firstNonZero2() template function works enough.

I have tried to extend it to more than one argument, creating firstNonZeroNa(), but it doesn't work. Do you know why?

firstNonZeroNb() works, despite being quite different (this is the basic version, without type consistency controls). But can you tell me why it doesn't need () to de-lazy its arguments?

In the D docs in the page about functions there are "Lazy Variadic Functions", can you tell me what they can be useful for?

Thank you,
bearophile


import std.stdio: writefln;

int f0a() { writefln("f0a"); return 0; }
int f0b() { writefln("f0b"); return 0; }
int f1() { writefln("f1"); return 1; }

T firstNonZero2(T)(T x, lazy T y) {
    if (x)
        return x;
    return y();
}

T firstNonZeroNa(T)(lazy T[] items...) {
    foreach (x; items[0 .. $-1])
        if (x)
            return x;
    return items[$-1];
}

Types[0] firstNonZeroNb(Types...)(lazy Types items) {
    foreach (x; items[0 .. $-1])
        if (x)
            return x;
    return items[$-1];
}

void main() {
    writefln(firstNonZero2(f0a(), f1()), \n);
    // temp.d(30): template temp.firstNonZeroNa(T) does not match any template declaration
    // writefln(firstNonZeroNa(f0a(), f0b(), f1()), \n);
    writefln(firstNonZeroNb(f0a(), f0b(), f1()));
}
March 13, 2008
Hi bearophile,
I gave a look at the problem and documentation, and I came up with the following solution, just before you left http://codepad.org/COfTfX6A
---------
import std.stdio: writefln;

int f0a() { writefln("f0a"); return 0; }
int f0b() { writefln("f0b"); return 0; }
int f1() { writefln("f1"); return 1; }

T firstNonZero(T)(T x) {
   return x;
}

T firstNonZero(T,U...)(T x, lazy U y) {
   if (x)
       return x;
   return firstNonZero(y);
}

void main() {
   writefln(firstNonZero(f0a(), f1(), f0b()));
}
---------

actually the () are optional also in your first example
ciao
Fawzi

On 2008-03-13 17:28:10 +0100, bearophile <bearophileHUGS@lycos.com> said:

> I am trying to write a small function that returns the first nonzero argument. For 2 arguments the following firstNonZero2() template function works enough.
> 
> I have tried to extend it to more than one argument, creating firstNonZeroNa(), but it doesn't work. Do you know why?
> 
> firstNonZeroNb() works, despite being quite different (this is the basic version, without type consistency controls). But can you tell me why it doesn't need () to de-lazy its arguments?
> 
> In the D docs in the page about functions there are "Lazy Variadic Functions", can you tell me what they can be useful for?
> 
> Thank you,
> bearophile
> 
> 
> import std.stdio: writefln;
> 
> int f0a() { writefln("f0a"); return 0; }
> int f0b() { writefln("f0b"); return 0; }
> int f1() { writefln("f1"); return 1; }
> 
> T firstNonZero2(T)(T x, lazy T y) {
>     if (x)
>         return x;
>     return y();
> }
> 
> T firstNonZeroNa(T)(lazy T[] items...) {
>     foreach (x; items[0 .. $-1])
>         if (x)
>             return x;
>     return items[$-1];
> }
> 
> Types[0] firstNonZeroNb(Types...)(lazy Types items) {
>     foreach (x; items[0 .. $-1])
>         if (x)
>             return x;
>     return items[$-1];
> }
> 
> void main() {
>     writefln(firstNonZero2(f0a(), f1()), \n);
>     // temp.d(30): template temp.firstNonZeroNa(T) does not match any template declaration
>     // writefln(firstNonZeroNa(f0a(), f0b(), f1()), \n);
>     writefln(firstNonZeroNb(f0a(), f0b(), f1()));
> }