コールキャッシングを実装する方法(メモイゼーション)
-
21-12-2019 - |
質問
メタデータアノテーションを使用して、邪魔な方法でコールキャッシュ(メモリ化)を実装したいです。
うまくいけば、それはこのように機能します:
class A{
@Cached
foo(msg) {
return msg;
}
}
void main() {
@Cached
var foo = ()=>"hello";
}
.
dart:mirrors
のみで実現できますか?
解決
このトピックで全体のブログ投稿をしばらくしました。ここでコピーするには長すぎるので、ここにリンクがあります:
http://dartery.blogspot.com/2012/09 / Memoizing-Functions-in-dart.html
上昇店は、高次のメモイ化関数を書くことができるが、Dartの柔軟なARGS関数の欠如による一般性に限られている。また、再帰関数で動的プログラミングを使用したい場合は、メモリングを念頭に置いて機能を書く必要があります。
他のヒント
私の現在の解決策を許す:
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
最初の電話: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();
}
. 所属していません StackOverflow