2016-02-10 28 views
5

Tôi có một lớp hiện có với một phương thức thể hiện buildHierarchyUncached có chữ ký có thể được tìm thấy bên dưới.Chức năng ghi nhớ Trong Kotlin

private fun buildHierarchyUncached(date: LocalDate): Node { ... } 

tôi muốn cung cấp một công chức năng buildHiearchy đó là một phiên bản memoized của buildHierarchyUncached. Tôi có thể lấy gần với những gì tôi muốn:

val buildHiearchy = Memoize<LocalDate, Node>({buildHierarchy(it)}) 

nào có thể được gọi như:

hierarchyService.buildHiearchy(businessDate) 

Sử dụng:

class Memoize<I, O>(val func: (I) -> O): (I) -> O{ 
    val cache = hashMapOf<I, O>(); 
    override fun invoke(p1: I): O { 
    return cache.getOrPut(p1, { func(p1) }) 
    } 
} 

Tôi muốn để có thể khai báo hàm memoized như một chức năng thay vì một tài sản, mà không phải là một vấn đề lớn, mặc dù tôi nghĩ rằng nó giúp dễ đọc. Như thế này:

fun buildHierarchy(date: LocalDate): Node = Memoize<LocalDate, Node>({ buildHierarchyUncached(it)}) 

nhưng không biên dịch: "Loại không phù hợp. Yêu cầu nút. Tìm thấy ghi nhớ".

Ngoài ra, tại sao bản dịch này không biên dịch?

val buildHiearchy = Memoize<LocalDate, Node>({(date) -> buildHierarchy(date)}) 
+0

Đối với những thứ có lỗi trình biên dịch, bạn nên đưa thông báo lỗi từ trình biên dịch để người khác có thể tìm kiếm/tìm câu hỏi SO này. –

+0

Đã thêm lỗi biên dịch mà tôi đã nhận được. –

Trả lời

4

Do bản chất của sự cố, bạn cần trường lớp để lưu bộ nhớ cache của bạn (giá trị được lưu trong bộ nhớ cache hoặc đối tượng bộ nhớ cache hoặc đại biểu). Vì vậy, bạn phải khai báo một lớp val ở một nơi nào đó, vì các hàm không thể làm điều đó.

Lưu ý rằng khi bạn khai báo giá trị buildHiearchy, bạn có hai thứ trong một: bạn lưu trữ đối tượng Memoize<..>(..) trong trường lớp và bạn nhận được hàm invoke() (được khai báo ở một nơi khác, nhưng vẫn ..). Tôi biết không có cách nào bạn có thể tuyên bố một chức năng và nhận được các lĩnh vực lưu trữ mà không có cú pháp bổ sung.

Đoạn mã sử dụng cú pháp lỗi thời. Khắc phục như thế này (không có dấu ngoặc đơn):

val buildHiearchy = Memoize<LocalDate, Node>({date -> buildHierarchy(date)}) 
+0

Câu trả lời của Elias sử dụng kết thúc và không yêu cầu một lớp học. Đoạn trích của bạn trả lời câu hỏi phụ nhưng không giải quyết được câu hỏi chính của tôi. Tôi đã chỉnh sửa câu hỏi để làm cho câu hỏi thực tế rõ ràng hơn. Cụ thể là, làm thế nào tôi có thể khai báo funcion được ghi nhớ như một hàm thay vì một thuộc tính. –

+0

tốt, đó là quan điểm của tôi - bạn không thể có một chức năng như vậy mà không có một lĩnh vực nào đó – voddan

1

Giải pháp sau đây hoạt động cho các hàm đối số đơn. Nếu bạn muốn tạo ra một phiên bản cache của hàm bar bạn chỉ cần khai báo nó như thế này:

val cachedBar = makeFunctionCache({ bar(it) }) 

Các cửa hàng thực hiện bộ nhớ cache trong một đóng cửa để bạn không cần phải đặt nó trong một lớp học chuyên dụng:

fun <X, R> makeFunctionCache(fn: (X) -> R): (X) -> R { 
    val cache: MutableMap<X, R> = HashMap() 
    return { 
     cache.getOrPut(it, { fn(it) }) 
    } 
} 
+0

Nó có lẽ không rõ ràng từ câu hỏi của tôi. Nhưng tôi muốn khai báo cachedBar như một hàm như: 'fun cachedBar (date: LocalDate): Node = makeFunctionCache ({date -> bar (date)})' –

+0

Bạn có thể sửa đổi câu hỏi của mình và giải thích chi tiết hơn chính xác những gì nó là bạn cần phải làm gì? Nó không rõ ràng với tôi tại sao giải pháp đóng cửa sẽ không hoạt động.Có vẻ như, và hoạt động như thế nào, bất kỳ chức năng nào khác. Có sự khác biệt nếu hàm thực sự là một phần của giao diện, nhưng nhiều thông tin hơn sẽ hữu ích. –

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