2012-10-01 7 views
6

No puedo averiguar cómo usar la función de memoria dentro de una clase.¿Cómo uso std.functional.memoize dentro de una clase?

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); 
} 

Esto da un error al intentar compilar: Error: la necesidad de 'esto' para acceder miembro de slowFunc

¿Cómo hago para hacer este trabajo?

+0

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

+0

Todavía obtiene el mismo error al compilar – WelshDragon

Respuesta

6

En realidad no es compatible con esto todavía. Podríamos presentar una solicitud de mejora. Aquí está mi implementación experimental:

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); 
} 

Los comentarios de tiempo son para mi máquina, por supuesto. :)

+0

Por cierto, esto no es semánticamente seguro. Los métodos necesitan la referencia 'this' porque normalmente tienen que buscar el estado interno de la clase (por ejemplo, los campos de clase). Si ese estado cambia entre llamadas, el resultado hash no se actualizará y obtendrá resultados obsoletos. Pero tal vez haya casos de uso legítimos para memorizar (los métodos de @pure vienen a la mente). Mejora archivada como: http://d.puremagic.com/issues/show_bug.cgi?id=8743 –

+0

Sin embargo, hay una manera de borrar el hash interno, pero tendría que hacer una verificación booleana en cada invocación. Por ejemplo: http://dpaste.dzfl.pl/abb6086f –

+0

Lo encontré: http://dpaste.dzfl.pl/4ba280c7 –

Cuestiones relacionadas