سؤال

أرغب في تنفيذ ذاكرة التخزين المؤقت للمكالمات (الحفظ) بطريقة غير تطفلية مع التعليقات التوضيحية للبيانات التعريفية.

نأمل أن يعمل مثل هذا:

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 إلى وظائف الوسائط المرنة.أيضًا، إذا كنت تريد استخدام البرمجة الديناميكية مع الدوال العودية، فأنت بحاجة إلى كتابة وظيفتك مع وضع الحفظ في الاعتبار - فهي تحتاج إلى أن تأخذ نفسها كوسيطة، حتى تتمكن من تمرير النسخة المحفوظة.

نصائح أخرى

الحل الحالي الخاص بي يسمح بما يلي:

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
النداء الأول لباز
المكالمة الأولى مع: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