memoize (is this a fix for overloading?)

Lars T. Kyllingstad public at kyllingen.NOSPAMnet
Wed Jan 5 02:24:04 PST 2011


On Wed, 05 Jan 2011 12:07:50 +0200, Max Samukha wrote:

> On 01/05/2011 11:21 AM, Lars T. Kyllingstad wrote:
>> On Tue, 04 Jan 2011 17:06:45 -0600, Andrei Alexandrescu wrote:
>>
>>> On 1/4/11 4:49 PM, %u wrote:
>>>>> There's still the risk of keeping multiple hashes. Consider:
>>>>
>>>>> ulong fun(ulong n) { ... }
>>>>> alias memoize!fun mfun;
>>>>
>>>>> mfun(5); // creates hash ulong[int]
>>>>> mfun(5u); // creates hash ulong[uint] mfun('5'); // creates hash
>>>>> ulong[char]
>>>>
>>>>
>>>> Ohhh I see... so you're basically looking for a compile-time version
>>>> of overload resolution, right? Because things seem to be getting
>>>> complicated very quickly.
>>>
>>> It's not that complicated; we'll be able to achieve it somehow.
>>> Overloads are compile-time entities so they should be easily
>>> inspectable.
>>
>> Since this is likely to be useful in other cases as well, maybe it
>> would be better to make a general template that selects an overload? 
>> So you'd use it like this:
>>
>>    alias memoize!(selectOverload!(sqrt, double)) msqrt;
>>
>> A first step towards this would be to make __traits(getOverloads) work
>> with module-level functions.  Currently it only works for member
>> functions.  Also it would probably be better if it accepted a function
>> alias instead of a string containing the function name.
> 
> __traits(getOverloads) does work with module level functions if you pass
> a module alias to it.

Cool!  I didn't know that.  Here's an updated version, where 
selectOverload works with both module-level and member functions:


module test;
import std.traits, std.stdio;

void foo(int i, double d) { writeln("Overload 1"); }
void foo(double d, int i) { writeln("Overload 2"); }

void main()
{
    alias selectOverload!(test, "foo", int, double) bar;
    bar(1, 3.0);    // Prints "Overload 1"

    alias selectOverload!(test, "foo", double, int) baz;
    baz(4.0, 2);    // Prints "Overload 2"
}



template selectOverload(alias parent, string fun, Params...)
{
    alias selectOverloadImpl!(Params.length, Params,
        __traits(getOverloads, parent, fun)) selectOverload;
}


template selectOverloadImpl(size_t lenP, A...)
{
    static assert (A.length > lenP, "No overload matches");
    static if (equalTuples!(lenP,
        A[0 .. lenP],
        ParameterTypeTuple!(A[lenP])))
    {
        alias A[lenP] selectOverloadImpl;
    }
    else
    {
        alias selectOverloadImpl!(lenP, A[0 .. lenP], A[lenP+1 .. $])
            selectOverloadImpl;
    }
}


template equalTuples(size_t len, T...)
{
    static if (len == 0 && T.length == 0)
        enum equalTuples = true;
    else static if (T.length != len*2)
        enum equalTuples = false;
    else static if (!is (T[0] == T[len]))
        enum equalTuples = false;
    else
        enum equalTuples =
            equalTuples!(len-1, T[1 .. len], T[len+1 .. $]);
}


More information about the Digitalmars-d mailing list