2012-12-12 39 views
72

Tôi sẽ bắt đầu bằng một ví dụ. Dưới đây là một tương đương với List.fill cho các bộ như một macro trong Scala 2.10:Tài liệu Scala 2.10 macro

import scala.language.experimental.macros 
import scala.reflect.macros.Context 

object TupleExample { 
    def fill[A](arity: Int)(a: A): Product = macro fill_impl[A] 

    def fill_impl[A](c: Context)(arity: c.Expr[Int])(a: c.Expr[A]) = { 
    import c.universe._ 

    arity.tree match { 
     case Literal(Constant(n: Int)) if n < 23 => c.Expr(
     Apply(
      Select(Ident("Tuple" + n.toString), "apply"), 
      List.fill(n)(a.tree) 
     ) 
    ) 
     case _ => c.abort(
     c.enclosingPosition, 
     "Desired arity must be a compile-time constant less than 23!" 
    ) 
    } 
    } 
} 

Chúng ta có thể sử dụng phương pháp này như sau:

scala> TupleExample.fill(3)("hello") 
res0: (String, String, String) = (hello,hello,hello) 

anh chàng này là một con chim lạ trong một vài khía cạnh. Đầu tiên, đối số arity phải là một số nguyên bằng chữ, vì chúng ta cần sử dụng nó ở thời gian biên dịch. Trong các phiên bản trước của Scala không có cách nào (theo như tôi biết) cho một phương pháp thậm chí để cho biết liệu một trong các đối số của nó là một thời gian biên dịch hay không.

Thứ hai, loại trả về is a lie —kiểu trả về tĩnh sẽ bao gồm loại nguyên tố và yếu tố cụ thể được xác định bởi các đối số, như được hiển thị ở trên.

Vậy làm cách nào để tôi ghi lại nội dung này? Tôi không mong đợi sự hỗ trợ của Scaladoc vào thời điểm này, nhưng tôi muốn có một ý thức về các quy ước hay thực hành tốt nhất (ngoài việc đảm bảo các thông báo lỗi biên dịch rõ ràng) sẽ làm cho chạy thành một phương thức macro - với nhu cầu kỳ lạ - ít gây ngạc nhiên cho người dùng thư viện Scala 2.10.

Các cuộc biểu tình trưởng thành nhất của hệ thống macro mới (ví dụ: ScalaMock, Slick, những người khác được liệt kê here) vẫn tương đối không có giấy tờ ở cấp phương pháp. Bất kỳ ví dụ hoặc con trỏ nào sẽ được đánh giá cao, bao gồm các ví dụ hoặc từ các ngôn ngữ khác với các hệ thống macro tương tự.

+12

Về ScalaMock, với tư cách là tác giả, tôi rất biết ơn các đề xuất về cách tôi có thể cải thiện tài liệu. ScalaMock thực sự là một DSL, vì vậy việc ghi lại các phương thức riêng lẻ không nhất thiết có ý nghĩa nhiều. Tôi đã cố gắng để tài liệu DSL như một toàn bộ ở đây: http://scalamock.org/api/index.html#org.scalamock.package và có bắt đầu tài liệu ở đây: http://www.paulbutcher.com/2012/10/scalamock3-step-by-step/Tôi có thể thêm gì để giúp? –

+2

@PaulButcher: Tôi không có ý chỉ trích ScalaMock và tôi đã chỉnh sửa câu trả lời để làm rõ hơn. Tôi đã tìm thấy đọc mã của bạn cực kỳ hữu ích như tôi đã cố gắng để hiểu các macro của Scala, và tôi nghĩ rằng các tài liệu cấp cao là rất rõ ràng. –

+8

Không phạm tội. Nhưng tôi chắc chắn sẽ đánh giá cao bất kỳ và tất cả các đề xuất cho những cách mà tôi có thể cải tiến. –

Trả lời

1

Tôi nghĩ cách tốt nhất để ghi lại những điều này là bằng mã ví dụ, như Miles đã thực hiện trong thử nghiệm macro based branch không có hình dạng của mình.

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