www.digitalmars.com         C & C++   DMDScript  

D - Template-like feature idea (wildcard variables)

reply David Caldwell <nospam indigita.com> writes:
Hello,
   I read about your D language recently and I really like it. You seem
to be trying to fix all the things that have been annoying me about
c/c++. 
   I have been pondering templates and #defines and what life would be
like without them. Clearly something should replace their funcitonality
in D. Here's my proposal for a replacement for template-ish functions
and macros:
It's pretty simple, just a new type: the wildcard type. I've been
representing it as a "*" as a reference to globbing and regexs but
perhaps * means too many things already. Heres a big example:

* min(* a, * b)
{
    if (a < b)
        return a;
    return b;
}

void swap(* inout a,* inout b)
{
    * temp;
    temp = a;
    a = b;
    b = temp;
}

*[] fillarray(* a, * b)
{
    *[] array;
    array[0] = a;
    array[1] = b;
    return array;
}

* GetYo(*a)
{
    return a.yo;
}

main()
{
    struct eat {
        int yo;
    }
    struct yikes {
        float yo;
    }
    eat e1,e2;
    yikes y1,y2;
    int i;
    float f;
    i = min(1,2);               // ok
    i = min(3,3.14);            // error (implicit cast, 2 possible
return types)
    i = min(3,cast(int) 3.13);  // ok (a and b are now both ints)
    i = min(3.1,3.14);          // error (return type wrong)
    i = cast(int) min(3.1,3.14) // ok (since it explicitly cast, it's ok)
    e1 = min(e1,e2);            // error (e1 < e2 fails in min()) (no
operator overloading yet)
    swap(y1,y2);                // ok
    swap(e1,e2);                // ok
    swap(y1,i);                 // error (temp used inconsistantly, y1 =
i fails)
    swap(y1,e1);                // error (temp used inconsistantly, y1 =
e1 fails)
    eat[] x = fillarray(e1,e2); // ok
    int[] y = fillarray(1,2);   // ok
    float[] z = fillarray(1,2); // error (return type wrong)
    f = GetYo(y1);              // ok
    f = GetYo(e1);              // error (return type wrong)
    f = cast(float) GetYo(e1);  // ok (since it explicitly cast, it's ok)
}

  Notice that types are not ever name (like the conventional "T" in
c++). My thinking is that it should be clear to the compiler what the
types should be and if they are inconsistant then it's an error. Thanks
to your great module idea the full source code to a wildcarded function
is available at compile time to make sure that the types really are
consistantly used. In the Swap() function the temp variable ends up
being the same type as a because it is set to "a" and so if it was any
other type it would be an error.

  Return values are determined by what type you actaully return. If a
function has multiple return statements with different return types then
that is an error.

  Therefore, the function that calls the wildcard function determines
the types of the arguments, but the wildcard function itself determines
the return type. In my examples here I've labelled implicit casting of
return values as illegal but I'm not 100% sure if thats right. It would
seem to cut down on errors, even if the implicit cast is normally legal.

  This is not addressing template classes, by the way. I've only thought
about functions so far...

  Any comments anyone? To limiting? To much implicitness? It's certainly
less verbose than c++ templates. And please forgive any obviously stupid
D syntax errors, this is my first D-ish program. :)

-David Caldwell
david        porkrind_org
Aug 18 2001
parent reply Russell Bornschlegel <kaleja estarcion.com> writes:
David Caldwell wrote:
 It's pretty simple, just a new type: the wildcard type. I've been
 representing it as a "*" as a reference to globbing and regexs but
 perhaps * means too many things already. [example snipped]

   Notice that types are not ever name (like the conventional "T" in
 c++). My thinking is that it should be clear to the compiler what the
 types should be and if they are inconsistant then it's an error. 
The biggest limitation I see here is that you can only specialize one type at a time here. If you want to write a generic associative array class, for example, you usually want to specialize by both lookup key and looked-up value. (Yeah, I know D already has associative arrays.) -Russell B
Aug 19 2001
parent David Caldwell <nospam porkrind.org> writes:
Russell Bornschlegel wrote:

 The biggest limitation I see here is that you can only specialize
 one type at a time here. If you want to write a generic associative
 array class, for example, you usually want to specialize by both
 lookup key and looked-up value. (Yeah, I know D already has
 associative arrays.)
No, maybe I didn't explain it properly. I guess all my examples were of one type, but this would work: * lookup(*[] a, * b) { for (int i=0;i<a.length;i++) if (a[i].key == b) return a[i].value; return void; // ??? unclear what this should be. maybe throw ??? } main() { struct assoc { int key; char[] value; } assoc[] a = { {1,"Hello"},{2,"there"} }; char[] s; s = lookup(a,1); // ok s = lookup(a,"hey"); // error a[i].key clashes with "b" in "if" statement int i = lookup(a,2); // error, return type clashes (its determined from "a[i].value") } -David david porkrind_org
Aug 20 2001