2013-05-30 26 views
6

Tôi đang cố gắng xác định loại tham số được chuyển vào macro ở thời gian biên dịch. Dường như nó hoạt động khi tôi sử dụng <:< nhưng không phải khi tôi sử dụng =:=. Tôi cung không chăc tại sao. ai đó có thể chỉ cho tôi phương hướng đúng không? Tôi đã bao gồm mã ví dụ bên dưới.Tại sao loại công bằng thất bại, nhưng loại sự phù hợp thành công trong macro này?

Macro này:

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

object Macros { 
    def say(param: Any): Unit = macro impl 

    def impl(c: Context)(param: c.Expr[Any]): c.Expr[Unit] = { 
    if (param.actualType.<:<(c.universe.typeOf[String])) { 
     c.universe.reify { printf("string: %s\n", param.splice) } 
    } else if (param.actualType.<:<(c.universe.typeOf[Int])) { 
     c.universe.reify { printf("int: %d\n", param.splice) } 
    } else { 
     c.universe.reify { printf("any: %s\n", param.splice) } 
    } 
    } 
} 

gọi bởi mã này:

object Test extends App { 
    Macros.say("Hi") 
    Macros.say(1) 
    Macros.say(Blah) 
} 

case object Blah 

Returns:

string: Hi 
int: 1 
any: Blah 

Nhưng nếu tôi kiểm tra bình đẳng loại (=:=) thay vì trở về vĩ mô:

any: Hi 
any: 1 
any: Blah 

Mọi trợ giúp sẽ được đánh giá cao.

Trả lời

7

Đó là vì loại "Hi" không chỉ là String, loại cụ thể hơn - String("Hi"), có nghĩa là loại này chứa thông tin thể hiện chuỗi ký tự bằng bê tông.

Tình huống tương tự xảy ra với nghĩa đen 1 - loại của nó là Int(1), không chỉ Int.

Bạn có thể sử dụng phương pháp widen trên Type dải thông tin về giá trị không đổi:

object Macros { 
    def say(param: Any): Unit = macro impl 

    def impl(c: Context)(param: c.Expr[Any]): c.Expr[Unit] = { 
    if (param.actualType.widen.=:=(c.universe.typeOf[String])) { 
     c.universe.reify { printf("string: %s\n", param.splice) } 
    } else if (param.actualType.widen.=:=(c.universe.typeOf[Int])) { 
     c.universe.reify { printf("int: %d\n", param.splice) } 
    } else { 
     c.universe.reify { printf("any: %s\n", param.splice) } 
    } 
    } 
} 
+5

+1, đánh tôi với nó. Cần lưu ý rằng 'Int (1)' được gọi là _singleton type_, tức là một kiểu chỉ có giá trị là '1', và' =: = 'sẽ hoạt động như mong đợi với các đối số không theo nghĩa đen (ví dụ' val i = 1; Macros.say (i) '). –

+0

Rực rỡ. Cảm ơn cả hai người! –

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