www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Lazy nonzero

reply bearophile <bearophileHUGS lycos.com> writes:
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()));
}
Mar 13 2008
parent Fawzi Mohamed <fmohamed mac.com> writes:
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()));
 }
Mar 13 2008