2012-10-01 27 views
6

Tôi không thể tìm ra cách sử dụng chức năng ghi nhớ bên trong một lớp học.Làm cách nào để sử dụng std.functional.memoize bên trong một lớp học?

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

này đưa ra một lỗi khi cố gắng biên dịch: Lỗi: cần 'này' để truy cập thành viên slowFunc

Làm thế nào tôi sẽ đi về làm công việc này?

+0

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

+0

Vẫn gặp lỗi tương tự khi biên dịch – WelshDragon

Trả lời

6

Nó chưa thực sự hỗ trợ tính năng này. Chúng tôi có thể gửi yêu cầu nâng cao. Đây là triển khai thử nghiệm của tôi:

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

Tất cả các bình luận về thời gian là dành cho máy của tôi. :)

+0

Btw không an toàn về mặt ngữ nghĩa. Các phương thức cần tham chiếu 'this' này vì chúng thường phải tìm kiếm trạng thái lớp bên trong (ví dụ: các trường lớp). Nếu trạng thái đó thay đổi giữa các cuộc gọi, kết quả được băm sẽ không được cập nhật và bạn sẽ nhận được kết quả lỗi thời. Nhưng có thể có các trường hợp sử dụng hợp pháp để ghi nhớ (phương pháp @pure xuất hiện trong đầu). Nâng cao được gửi dưới dạng: http://d.puremagic.com/issues/show_bug.cgi?id=8743 –

+0

Có một cách để xóa băm nội bộ, nhưng bạn sẽ phải thực hiện kiểm tra boolean trên mọi lệnh gọi. Ví dụ: http://dpaste.dzfl.pl/abb6086f –

+0

Đã tìm ra: http://dpaste.dzfl.pl/4ba280c7 –

Các vấn đề liên quan