SarahB
SarahB

Reputation: 328

Writing a scala function which can take Int or Double values

I have written a function to accept the below type of values: (1, Array(1.0,2.0,3.0)) That is a Tuple with Int being first value and next being an Array of Doubles.

I would also like it to accept an Array of Integers as well. The function I have written is as below:

def getCountsAndAverages[T](Parameter: Tuple2[Int, Array[T]])(implicit n:Numeric[T]) = {
(Parameter._1, (Parameter._2.size,   Parameter._2.map(n.toDouble).sum/Parameter._2.size)) 
}

The tuple's first parameter is a number and then its an Array of number of times it appears in the file.

It is working fine for sample cases, however I am reading a text file which has the data in the same format as needed for this function to work. I am calling this function using 'map' operation as:

parsedfile.map(getCountsAndAverages)

I am getting the below errors:

◾could not find implicit value for parameter n: Numeric[T]
◾not enough arguments for method getCountsAndAverages: (implicit n: Numeric[T])(Int, (Int, Double)). Unspecified value parameter n.

I would be grateful for any help or suggestions

Upvotes: 5

Views: 3063

Answers (2)

Alexey Romanov
Alexey Romanov

Reputation: 170745

  1. Iterable isn't Array, so your function can't work on it. You can define def getCountsAndAverages[T](Parameter: Tuple2[Int, Iterable[T]])(implicit n:Numeric[T]) instead. But in this case Parameter._2.map(n.toDouble).sum/Parameter._2.size may be inefficient, depending on the actual runtime type of Parameter._2. You may want to write it as a fold instead.

  2. Change the map call to parsedfile.map(getCountsAndAverages(_)).

When you write parsedfile.map(getCountsAndAverages), it is converted to an anonymous function using eta-expansion. But is seems to happen before type parameter inference, so you end up with (x: T) => getCountsAndAverages(x) for arbitrary T, which doesn't compile. parsedfile.map(getCountsAndAverages[Double]) works as well. This is a known unresolved issue: https://issues.scala-lang.org/browse/SI-7641.

Upvotes: 1

Nagarjuna Pamu
Nagarjuna Pamu

Reputation: 14825

You can use any one of the following syntax

def foo[T](x: T)(implicit n: Numeric[T]) = n.toDouble(x)

or

def foo[T : Numeric](x: T) = implicitly[Numeric[T]].toDouble(x)

In your case

def getCountsAndAverages[T: Numeric](Parameter: Tuple2[Int, Array[T]]) = {
 (Parameter._1, (Parameter._2.size, Parameter._2.map(implicitly[Numeric[T]].toDouble(_)).sum / Parameter._2.size))
}

Upvotes: 3

Related Questions