Pregunta

Quiero implementar el caché de llamadas (memorización) de forma no intrusiva con las anotaciones de metadatos.

Con suerte, funcionará así:

class A{
  @Cached
  foo(msg) {
    return msg;
  }
}

void main() {
  @Cached
  var foo = ()=>"hello";
}

¿Se puede lograr con sólo dart:mirrors ?

¿Fue útil?

Solución

Escribí una publicación completa de blog en este tema hace un tiempo.Es demasiado largo para copiar aquí, así que aquí está el enlace:

http://dartery.blogspot.com/2012/09 / Memoizing-functions-in-dart.html

El resultado es que puede escribir funciones de memoriz de orden superior, pero están limitadas en generalidad por la falta de funciones de Args Flexibles de DART.Además, si desea utilizar la programación dinámica con funciones recursivas, debe escribir su función con la memorización en mente, debe tomarse como un argumento, por lo que puede pasar en la versión memoIcada.

Otros consejos

Mi solución actual permite:

class B {
  @CachedCallName(#cachedBaz)
  baz() => print("first call to baz");
}
class A extends B with CacheableCalls {
  @CachedCallName(#foo)
  _foo(msg) {
    print("first call with: $msg");
    return msg + msg;
  }
}
void main() {
  A a = new A();
  print(a.foo(21));
  print(a.foo(21));
  a.cachedBaz();
  print(a.foo(22));
  a.cachedBaz();
}

Producción:

primera llamada con:21
42
42
primera llamada a baz
primera llamada con:22
44

Defectos:
- No se pueden almacenar en caché los métodos con sus nombres reales.
- puede ampliar la vista de colección pero no puede almacenar en caché los operadores existentes como operator []
- No se pueden almacenar en caché las funciones.

Fuente completa:

@MirrorsUsed(metaTargets: CachedCallName)
import 'dart:mirrors';

class CachedCallName {
  final Symbol name;
  const CachedCallName(this.name);
}
@proxy
class CacheableCalls {
  Map _cache = new Map();
  dynamic _chacheInvoke(InstanceMirror thisMirror, Symbol
      methodName, Invocation invocation) {
    String key = "$methodName${invocation.positionalArguments}"
        "${invocation.namedArguments}";
    if (_cache.containsKey(key)) {
      return _cache[key];
    } else {
      InstanceMirror resultMirror = thisMirror.invoke(methodName,
          invocation.positionalArguments, invocation.namedArguments);
      _cache[key] = resultMirror.reflectee;
      return resultMirror.reflectee;
    }
  }
  dynamic noSuchMethod(Invocation invocation) {
    bool isFound = false;
    var result;
    Symbol called = invocation.memberName;
    InstanceMirror instanceMirror = reflect(this);
    ClassMirror classMirror = instanceMirror.type;
    classMirror.instanceMembers.forEach((Symbol name, MethodMirror mm) {
      mm.metadata.forEach((InstanceMirror im) {
        if (im.reflectee is CachedCallName) {
          if (im.reflectee.name == called) {
            isFound = true;
            result = _chacheInvoke(instanceMirror, name, invocation);
          }
        }
      });
    });

    if (isFound) {
      return result;
    } else {
      throw new NoSuchMethodError(this, called,
          invocation.positionalArguments, invocation.namedArguments);
    }
  }
}
class B {
  @CachedCallName(#cachedBaz)
  baz() => print("first call to baz");
}
class A extends B with CacheableCalls {
  @CachedCallName(#foo)
  _foo(msg) {
    print("first call with: $msg");
    return msg + msg;
  }
}
void main() {
  A a = new A();
  print(a.foo(21));
  print(a.foo(21));
  a.cachedBaz();
  print(a.foo(22));
  a.cachedBaz();
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top