2013-03-06 25 views
5

Để phản hồi lại this question, tôi đã có một bước tiến triển khai biểu thức kiểu Haskell 'where' ở Scala bằng cách sử dụng nhánh thiên đường vĩ mô. Mã có sẵn tại scala-where. bây giờ tôi có thể viết một cái gì đó như sau:Scala untyped macro ở vị trí infix

val result = where (f1(1) * f2(2), { 
    def f1(x : Int) = x + 1 
    def f2(x : Int) = x + 2 
}) 

Tuy nhiên, những gì tôi thực sự muốn làm là để có thể gọi đây là ở vị trí trung tố:

val result = (f1(1) * f2(2)) where { 
    def f1(x : Int) = x + 1 
    def f2(x : Int) = x + 2 
} 

Thông thường, các loại điều này sẽ dễ dàng, nhưng tôi không thể thấy cách thực hiện nó bằng cuộc gọi macro. Biểu thức (f1 (1) * f2 (2)) sẽ không gõ trước ứng dụng macro, vì vậy một cái gì đó như xây dựng một lớp giá trị tiềm ẩn không hoạt động. Có cách nào để nhận cú pháp kiểu này không?

Không này, chỉ có hai danh sách tham số để người ta có thể làm:

val result = where (f1(1) * f2(2)) { 
    def f1(x : Int) = x + 1 
    def f2(x : Int) = x + 2 
} 

sẽ được tốt đẹp, nhưng một lần nữa điều này dường như khó khăn. Có thể gọi một macro với hai danh sách tham số không?

Trả lời

2

Đối với tùy chọn đầu tiên: Tôi nghĩ bạn có thể làm cho chuyển đổi tiềm ẩn thành macro không được nhập chính xác, phải không?

Đối với tùy chọn thứ hai: Bạn có thể gọi macro bằng nhiều danh sách tham số, có. Nhiều danh sách tại trang web cuộc gọi sẽ chuyển đến nhiều danh sách tại vị trí định nghĩa, ví dụ:

def myMacro(a: _)(b: _) = macro myMacro_impl 

def myMacro_impl(c: Context)(a: c.Tree)(b: c.Tree): c.Tree = { ... } 

sẽ được gọi là:

myMacro(...)(...) 
+1

Hai tham số điều là rất tốt, cảm ơn! Tôi bằng cách nào đó đã bỏ lỡ điều đó. – Impredicative

+1

Liên quan đến việc chuyển đổi tiềm ẩn - Tôi không chắc chắn làm thế nào để có được móc vào hệ thống vĩ mô. Tôi không nghĩ rằng nó có thể là một chuyển đổi tiềm ẩn, vì chắc chắn cây phải được đánh máy để tìm kiếm các chuyển đổi? – Impredicative

+0

Bạn có thể đúng, mặc dù tôi nghĩ bạn sẽ có thể thực hiện 'ngầm định def conv = macro conv_impl; def conv_impl (c: Bối cảnh) (x: c.Tree): c.Expr [T] 'và về cơ bản nó thuộc kiểu' Any => T' –

1

Trả lời: như của 2013/03/08 nó là không thể để sử dụng macro chưa được nhập ở vị trí cố định. Trích dẫn từ Eugene Burmako trên scala-user mailing list:

Hiện nay đối số bên trái phải được typechecked đầu tiên trước khi bất kỳ đá độ phân giải tiềm ẩn trong Thực tế là bạn có thể viết "class foo (x: _)". Là giám sát - cú pháp gạch dưới được cho là chỉ hoạt động trong các macro chưa được nhập.

Để tham khảo, gần nhất tôi đến việc có thể để làm điều này là như sau: danh sách

implicit class HasWhere(val exp : _) { 
def where(block : Unit) = macro whereInfix 
} 

def whereInfix(c : Context)(block : c.Expr[Unit]) = { 
    import c.universe._ 

    val exp = Select(c.prefix.tree, TermName("exp")) 
    val Expr(Block((inner, _))) = block 
    val newinner = inner :+ exp 
    Block(newinner : _*) 
} 
Các vấn đề liên quan