2014-11-03 136 views
1

假設我有類型AB,和C,和一個重載的方法:包裝重載函數

def foo(a: A): C 
def foo(b: B): C 

然後假設我有一個(複雜)的代碼與工作C類型的對象。我想有是採取兩種類型AB的方法:

def bar(x: [A or B]) = { 
    val c = foo(x) 
    // Code that works with c 
} 

當然,我可以寫的bar兩個版本,重載採取類型AB,但在這種情況下,有多個函數的行爲類似bar,並且對於所有這些函數來說,重載版本(在我的實際案例中,有foo有三個版本)將是愚蠢的。

C風格的宏在這裏是完美的,所以我想看看Scala的宏。尷尬的是,Scala的宏仍類型化檢查,所以我不能隨便說

reify(foo(x.splice)) 

因爲編譯器想知道的x類型事前。我對使用Scala宏(它是一個實質性的API)完全陌生,所以在這方面的一些指針將不勝感激。

或者如果有一種方法來佈局沒有宏的代碼,這也會有幫助!

+3

你可能可以用宏來做這樣的事情,但這真的不是一個好主意(我認爲這是作爲Scala宏觀系統的粉絲)。改爲使用類型類。 – 2014-11-03 19:13:53

+0

是的,類型類是一個整潔的想法。不過,我想知道(爲了教育目的)是否有辦法處理宏?似乎應該是可能的。 – geoffliu 2014-11-03 20:04:55

回答

1

你可以以不同的方式解決你的問題。

而不是說類型A or B想想你想從這些類型。在你的例子中,如果你說:「它是什麼類型並不重要,只要我有一個foo方法」。這就是下面的代碼所示:

trait FooMethod[T] { 
    def apply(t:T):C 
} 

object FooMethod { 
    implicit val forA = new FooMethod[A] { 
    def apply(a:A):C = foo(a) 
    } 

    implicit val forB = new FooMethod[B] { 
    def apply(b:B):C = foo(b) 
    } 
} 

def bar[X](x: X)(implicit foo:FooMethod[X]) = { 
    val c = foo(x) 
    // Code that works with c 
}