Search code examples
scalalistmultiplication

Scala: How to multiply a List of Lists by value


Now studying Scala and working with list of lists. Want to multiply array by an element(for example, 1).

However I get the following error:

identifier expected but integer constant found

Current code:

def multiply[A](listOfLists:List[List[A]]):List[List[A]] =
if (listOfLists == Nil) Nil
else -1 * listOfLists.head :: multiply(listOfLists.tail) 
val tt = multiply[List[3,4,5,6];List[4,5,6,7,8]]
print(tt);;

Solution

  • There are a few issues with your code:

    1. In general, you can't perform arithmetic on unconstrained generic types; somehow, you have to communicate any supported arithmetic operations.
    2. Multiplying by 1 will typically have no effect anyway.
    3. As already pointed out, you don't declare List instances using square brackets (they're used for declaring generic type arguments).
    4. The arguments you're passing to multiply are two separate lists (using an invalid semicolon separator instead of a comma), not a list of lists.
    5. In the if clause the return value is Nil, which matches the stated return type of List[List[A]]. However the else clause is trying to perform a calculation which is multiplying List instances (not the contents of the lists) by an Int. Even if this made sense, the resulting type is clearly not a List[List[A]]. (This also makes it difficult for me to understand exactly what it is you're trying to accomplish.)

    Here's a version of your code that corrects the above, assuming that you're trying to multiply each member of the inner lists by a particular factor:

    // Multiply every element in a list of lists by the specified factor, returning the
    // resulting list of lists.
    //
    // Should work for any primitive numeric type (Int, Double, etc.). For custom value types,
    // you will need to declare an `implicit val` of type Numeric[YourCustomType] with an
    // appropriate implementation of the `Numeric[T]` trait. If in scope, the appropriate
    // num value will be identified by the compiler and passed to the function automatically.
    def multiply[A](ll: List[List[A]], factor: A)(implicit num: Numeric[A]): List[List[A]] = {
    
      // Numeric[T] trait defines a times method that we use to perform the multiplication.
      ll.map(_.map(num.times(_, factor)))
    }
    
    // Sample use: Multiply every value in the list by 5.
    val tt = multiply(List(List(3, 4, 5, 6), List(4, 5, 6, 7, 8)), 5)
    println(tt)
    

    This should result in the following output:

    List(List(15, 20, 25, 30), List(20, 25, 30, 35, 40))
    

    However, it might be that you're just trying to multiply together all of the values in the lists. This is actually a little more straightforward (note the different return type):

    def multiply[A](ll: List[List[A]])(implicit num: Numeric[A]): A = ll.flatten.product
    
    // Sample use: Multiply all values in all lists together.
    val tt = multiply(List(List(3, 4, 5, 6), List(4, 5, 6, 7, 8)))
    println(tt)
    

    This should result in the following output:

    2419200
    

    I'd recommend you read a good book on Scala. There's a lot of pretty sophisticated stuff going on in these examples, and it would take too long to explain it all here. A good start would be Programming in Scala, Third Edition by Odersky, Spoon & Venners. That will cover List[A] operations such as map, flatten and product as well as implicit function arguments and implicit val declarations.