2012-10-01 12 views
6

Ich bin nicht in der Lage, herauszufinden, wie Sie die Memoize-Funktion in einer Klasse verwenden.Wie verwende ich std.functional.memize in einer Klasse?

import std.functional; 

class A { 
    int slowFunc(int a, int b) { 
     return 0; 
    } 

    alias memoize!slowFunc fastFunc; 
} 

void main() { 
    auto a = new A; 
    a.fastFunc(1,2); 
} 

Dies gibt einen Fehler, wenn sie versuchen zu kompilieren: Fehler: Notwendigkeit ‚dieses‘ zugreifen Mitglied slowFunc

Wie würde ich darum, diese Arbeit zu gehen?

+0

und 'alias memoize! (This.slowFunc) fastFunc;'? –

+0

Immer noch den gleichen Fehler beim Kompilieren – WelshDragon

Antwort

6

Es unterstützt dies eigentlich noch nicht. Wir könnten eine Verbesserungsanfrage einreichen. Hier ist meine experimentelle Implementierung:

import std.stdio; 
import std.traits; 
import std.typecons; 
import std.datetime; 

template isClassStruct(alias fun) 
{ 
    enum bool isClassStruct = (is(fun == class) || is(fun == struct)); 
} 

mixin template memoize(alias fun, uint maxSize = uint.max) 
    if (isClassStruct!(__traits(parent, fun))) 
{ 
    ReturnType!fun opCall(ParameterTypeTuple!fun args) 
    { 
     static ReturnType!fun[Tuple!(typeof(args))] memo; 
     auto t = tuple(args); 
     auto p = t in memo; 
     if (p) return *p; 
     static if (maxSize != uint.max) 
     { 
      if (memo.length >= maxSize) memo = null; 
     } 

     mixin("auto r = this." ~ __traits(identifier, fun) ~ "(args);"); 
     memo[t] = r; 
     return r; 
    }  
} 

class A 
{ 
    int slowFunc(int a, int b) 
    { 
     int result; 
     foreach (_; 0 .. 1024) 
     { 
      result += a; 
      result += b; 
     } 
     return result; 
    } 

    mixin memoize!slowFunc fastFunc; 
} 

enum CallCount = 2048; 

void main() 
{ 
    A a = new A; 

    auto sw1 = StopWatch(AutoStart.yes); 
    foreach (x; 0 .. CallCount) 
    { 
     a.slowFunc(100, 100); // 11232 usecs 
    } 
    sw1.stop(); 
    writeln(sw1.peek.usecs); 

    auto sw2 = StopWatch(AutoStart.yes); 
    foreach (x; 0 .. CallCount) 
    { 
     a.fastFunc(100, 100); // 302 usecs 
    } 
    sw2.stop(); 
    writeln(sw2.peek.usecs); 
} 

Die Timing Kommentare sind für meine Maschine natürlich. :)

+0

Btw das ist nicht semantisch sicher. Methoden benötigen die 'this'-Referenz, da sie normalerweise den internen Klassenstatus (z. B. Klassenfelder) nachschlagen müssen. Wenn dieser Status zwischen den Aufrufen wechselt, wird das Hashergebnis nicht aktualisiert und Sie erhalten veraltete Ergebnisse zurück. Aber vielleicht gibt es legitime Anwendungsfälle für das Memoisieren (@pure-Methoden kommen mir in den Sinn). Erweiterung eingereicht als: http://d.puremagic.com/issues/show_bug.cgi?id=8743 –

+0

Es gibt zwar eine Möglichkeit, den internen Hash zu löschen, aber Sie müssten bei jedem Aufruf eine boolesche Überprüfung durchführen. Zum Beispiel: http://dpaste.dzfl.pl/abb6086f –

+0

Ich habe es herausgefunden: http://dpaste.dzfl.pl/4ba280c7 –

Verwandte Themen