2015-06-19 140 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

我明白了。所以这只是解决方法超载模糊的问题。如果错误信息更明确,那将会很好。 –