2015-06-19 93 views
2

我正在嘗試爲Scala編寫一個查詢庫。這是迄今爲止代碼:斯卡拉錯誤:缺少擴展功能的參數類型

class Query[TElement](source: Traversable[TElement]) { 
    def join[TOther](other: Traversable[TOther]) = new { 
     def on[TKey](keySelector1: TElement => TKey) = new { 
      def equals(keySelector2: TOther => TKey) = new { 
       def into[TResult](resultSelector: (TElement, TOther) => TResult): Query[TResult] = { 
        val map = source.map(e => (keySelector1(e), e)).toMap 
        val results = other 
         .map(e => (keySelector2(e), e)) 
         .filter(p => map.contains(p._1)) 
         .map(p => (map(p._1), p._2)) 
         .map(p => resultSelector(p._1, p._2)) 
        new Query[TResult](results) 
       } 
      } 
     } 
    } 
} 

object Query { 
    def from[TElement](source: Traversable[TElement]): Query[TElement] = { 
     new Query[TElement](source) 
    } 
} 

...

val results = Query.from(users) 
    .join(accounts).on(_.userId).equals(_.ownerUserId).into((_, _)) 

我收到以下錯誤,當我去編譯:

error: missing parameter type for expanded function ((x$2) => x$2.ownerUserId) 

我有點困惑,爲什麼我會在非通用函數equals上得到這個錯誤。我想,它的通用參數來自外部範圍。我知道要解決它,我必須通過編寫(a: Account) => a.ownerUserId明確說明參數類型。但是,我試圖使它成爲一個非常流利的庫,這使它變得混亂。

回答

2

問題很簡單。從Any繼承的現有方法equals存在歧義。簡單的例子:

scala> class X[A, B] { def equals(f: A => B) = f } 
defined class X 

scala> val x = new X[Int, String] 
x: X[Int,String] = [email protected] 

scala> x.equals((x: Int) => x.toString) 
res0: Int => String = <function1> 

scala> x.equals((x: String) => x.toString) // uh-oh 
res1: Boolean = false 

正如人們可以在最後一個例子看,當錯誤的函數類型傳遞,編譯器必須選擇def equals(Any): Boolean。如果不指定任何類型,編譯器必須推斷一個,這在示例中無法實現。

只需將您的方法重命名爲其他內容,問題就消失了。

+0

我明白了。所以這只是解決方法超載模糊的問題。如果錯誤信息更明確,那將會很好。 –