memoize (is this a fix for overloading?)
Max Samukha
spambox at d-coding.com
Wed Jan 5 03:40:05 PST 2011
On 01/05/2011 12:24 PM, Lars T. Kyllingstad wrote:
> 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 .. $]);
> }
Nice! Though I think that overloads should be selected not by type
equality but by regular overload resolution rules. That is the template
should take not parameter but argument types.
More information about the Digitalmars-d
mailing list