문제

메타 데이터 주석을 사용하여 호출되지 않는 방식으로 호출 캐시 (메모)를 구현하고 싶습니다.

잘하면 이렇게 작동합니다.

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

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

dart:mirrors만으로도 얻을 수 있습니까?

도움이 되었습니까?

해결책

이 주제에 전체 블로그 게시물을 썼습니다.여기에 복사하는 것이 너무 깁니다. 그래서 링크가 있습니다 :

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

상위 메모 화 기능을 작성할 수 있지만 DART의 유연한 ARGS 기능이 부족하여 일반성이 제한적이라는 점입니다.또한 재귀 함수로 동적 프로그래밍을 사용하려면 Memoization과 함께 함수를 쓸 필요가 있습니다. 인수로 스스로 수행해야하므로 메모화 된 버전을 통과 할 수 있습니다.

다른 팁

내 전류 솔루션은 다음을 허용합니다 :

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

출력 :

첫 번째 전화 : 21
42
42
Baz



첫 번째 전화 : 22
44

결함 :

- 실제 이름으로 메소드를 캐시 할 수 없습니다.
- 콜렉션보기를 확장 할 수 있지만 operator []와 같은 기존 연산자를 캐시 할 수 없습니다
- 함수를 캐시 할 수 없습니다.

전체 출처 :

@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();
}
.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top