2017-10-13 46 views
2

我想要一个通用函数来对列表中的值求和。斯卡拉数值总和列表

下面的代码无法编译:

def sum[T : Numeric](x: List[T]): T = { 
    if(x.isEmpty) 0 
    else x.head + sum(x.tail) 

    } 

的编译错误是:

error: type mismatch; 

[INFO] found : Int(0) 

[INFO] required: T 

[INFO]  if(x.isEmpty) 0 
+0

为什么不使用'x.sum'(其中'x'是一个'列表[T]'和'T'有一个隐式'数值[T] '定义的实例)? –

+0

我在网上遇到了代码片断,并对我如何使它更通用感到好奇。这是一个了解斯卡拉的练习(我不在学校,只是好奇) – Jake

+1

顺便说一句,有一件事要注意这种类型的功能:它不是_tail递归_。如果你有一个很长的列表,你可以得到一个_stack overflow_。 (现在我在哪里听到过这个表达式?)对于函数是尾递归的,递归调用必须是最后一个表达式。 –

回答

4

此错误是告诉你,你所指定的返回类型为T,但你总是返回一个0作为空列表,这是一个Int。如果传入的列表包含其他内容,例如TDouble还是某种自定义类型?试试这个:

if(x.isEmpty) implicitly[Numeric[T]].zero 

完整的工作方法:

def sum[T : Numeric](x: List[T]): T = { 
    if (x.isEmpty) implicitly[Numeric[T]].zero 
    else implicitly[Numeric[T]].plus(x.head, sum(x.tail)) 
} 

或者:

def sum[T](x: List[T])(implicit num: Numeric[T]): T = { 
    import num._ 
    if (x.isEmpty) zero 
    else x.head + sum(x.tail) 
} 
+0

您错过了'Numeric [T]]。 ;) –

+0

是的,因为否则:错误:类型不匹配; [INFO] found:List [T] [INFO] required:List [String] [INFO] else x.head + sum(x.tail) – Jake

+0

现在除了现在我得到“不能隐式地解析符号'” – Jake

2

试试这个:

def sum[T](x: List[T])(implicit num: Numeric[T]): T = x.foldLeft(num.zero)(num.plus) 
1

使用reduce(如果你不想设置对于总和ITAL值)以其他方式使用fold操作:

def sumWithReduce[T](lst: List[T])(implicit numericType: Numeric[T]):T 
= lst.reduce(numericType.plus) 

def sumWithFold[T](lst: List[T])(implicit numericType: Numeric[T]):T 
= lst.fold(numericType.zero)(numericType.plus) 
+0

'reduce'失败的空列表,'fold'更强大。 –