2012-06-28 23 views
5

Tôi phải tích hợp một số macro trong một dự án đang sử dụng mẫu bánh. Mô hình đó cho phép chúng tôi tránh được hàng tỷ hàng nhập khẩu, trong số những lợi thế khác, vì vậy chúng tôi muốn giữ nó. Bây giờ, chúng tôi đang đối mặt với một vấn đề với một số macro thử nghiệm, chúng tôi đã thử nghiệm bên ngoài thân cây. Đầu tiên, chúng ta hãy thể hiện một hệ thống giả tên Cake:Có thể tích hợp Cake-Pattern và Macros không?

trait APiece { 
    class A 
} 

trait BPiece { this: APiece => 
    def aMacro(a: A): Unit =() /* macro ??? */ 
} 

trait CPiece { this: APiece with BPiece => 
    def aMacroInvoker = aMacro(new A) 
} 

class Cake { this: APiece with BPiece with CPiece => } 

mỗi người định nghĩa một lớp, BPiece được coi là một macro trong đó sử dụng các lớp mỗi người được xác định, và cuối cùng, CPiece gọi vĩ mô. Tôi nói rằng BPiece được cho là một vĩ mô vì tôi không thể viết mã cho việc triển khai nó. Tôi đã thử nhiều cách nhưng tôi luôn sụp đổ với các lỗi sau:

"macro implementation must be in statically accessible object" 

Đọc macros code người ta có thể đoán rằng nó là neccesary gửi kèm macro trong một module tĩnh. Có cách nào để triển khai macro sử dụng cấu trúc hệ thống không?

Trả lời

4

May mắn là có một giải pháp dễ dàng cho vấn đề của bạn.

Nhưng trước tiên, hãy để tôi xem xét lại. Trong nguyên mẫu đầu tiên, các macro được định nghĩa như sau: def macro aMacro(a: A): Unit = .... Một trong những đột phá lớn mà chúng tôi đã có khi chuẩn bị SIP là tách các định nghĩa macro (các khuôn mặt công khai của macro) và triển khai macro (biến thể cây lưu trữ logic macro). Phải mất một thời gian tôi mới nhận ra điều này thật tuyệt vời, nhưng bây giờ tôi rất vui mừng mỗi khi tôi viết một tuyên bố vĩ mô.

Vì vậy, hãy quay lại câu hỏi của bạn. Chắc chắn, việc triển khai macro phải được truy cập tĩnh (nếu không, trình biên dịch sẽ không thể tải và gọi chúng trong quá trình biên dịch). Tuy nhiên định nghĩa vĩ mô không có hạn chế này, vì vậy bạn có thể viết định nghĩa như thế:

trait BPiece { this: APiece => 
    def aMacro(a: A): Unit = macro Macros.aMacro 
} 

thực hiện Macro được gọi từ định nghĩa có thể đưa vào bất kỳ vật gì bạn muốn, thậm chí thành một đơn vị biên dịch khác nhau .

Mảnh ghép duy nhất còn thiếu là cách chúng tôi sẽ tham khảo A từ việc triển khai, vì A được xác định bên trong một chiếc bánh. Cách đơn giản nhất là tạo aMacro chung và dựa vào suy luận kiểu:

(cập nhật: để làm ví dụ này hoạt động ở 2.10.0-M7, bạn cần thay thế c.TypeTag bằng c.AbsTypeTag; để tạo ví dụ này làm việc trong 2.10.0-RC1, c.AbsTypeTag cần phải được thay thế bằng c.WeakTypeTag)

trait BPiece { this: APiece => 
    def aMacro[A](a: A): Unit = macro Macros.aMacro[A] 
} 

object Macros { 
    def aMacro[A: c.TypeTag](c: Context)(a: c.Expr[A]): c.Expr[Unit] = c.literalUnit 
} 

này sẽ không cho phép bạn sử dụng reify, mặc dù, bởi vì đối với việc thực hiện vĩ mô A chỉ là một tham số kiểu mà không bất kỳ thành viên nào. Cũng sẽ có vấn đề nếu bạn muốn trả lại thứ gì đó đặc trưng cho bánh từ macro, nhưng hãy giải quyết chúng khi chúng phát sinh. Vui lòng gửi câu hỏi tiếp theo nếu bạn cần.

+2

Tôi không nghĩ rằng giải quyết vấn đề của mình, và tôi không nghĩ bất cứ điều gì sẽ xảy ra. Bản chất của mẫu bánh - như bạn nên biết! :-) - đang có thể chọn các lớp bạn muốn trong mã "khách hàng". Nếu 'Macro 'là tĩnh, bạn không thể chuyển đổi theo ý muốn. Bạn có thể chuyển đổi tệp nguồn hoặc tệp lớp, nhưng bạn không thể viết mã cho biết "điều này sẽ sử dụng macro từ đây và sẽ sử dụng macro từ đó". –

+0

Tuyệt vời, tôi nghĩ rằng vấn đề mới sẽ nảy sinh, nhưng bây giờ tôi có thể tiếp tục với giải pháp này. Cảm ơn nhiều!Daniel, hệ thống của chúng ta sẽ không thực sự thuần khiết với các macro. Chúng tôi chỉ cho phép khách hàng quyết định xem anh ấy có muốn sử dụng chúng hay không. Vì vậy, tôi hy vọng điều này là đủ tốt. – jeslg

+0

@ DanielC.Sobral Tôi mặc dù ý tưởng là tuyên bố một macro bên trong một chiếc bánh. Nếu bạn có các lớp khác nhau xác định các macro đề cập đến các triển khai macro khác nhau, bạn có thể chuyển đổi giữa các macro theo ý muốn và nhận được hành vi khác nhau. –

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