0

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);;
Community
  • 1
  • 1
Horwett
  • 23
  • 4
  • You need to straighten out syntax. In Scala you have to pass **types** in square brackets. You're trying to pass **values**, again, with the wrong syntax. You probably want to do something like `multiply(List(List(3,4,5,6), List(4,5,6,7,8)))`. Also in Scala you generally don't need semicolons. – yahor Nov 16 '17 at 01:13
  • Your question is very unclear. Can you provide a *precise* specification of what it is that you want to happen, including any and all rules, exceptions from those rules, corner cases, special cases, boundary cases, and edge cases? Can you provide sample inputs and outputs demonstrating what you expect to happen, both in normal cases, and in all the exceptions, corner cases, special cases, boundary cases, and edge cases? – Jörg W Mittag Nov 16 '17 at 06:33

2 Answers2

2

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.

Mike Allen
  • 8,139
  • 2
  • 24
  • 46
1

To make numeric operations available to type A, you can use context bound to associate A with scala.math.Numeric which provides methods such as times and fromInt to carry out the necessary multiplication in this use case:

def multiply[A: Numeric](listOfLists: List[List[A]]): List[List[A]] = {
  val num = implicitly[Numeric[A]]
  import num._
  if (listOfLists == Nil) Nil else
    listOfLists.head.map(times(_, fromInt(-1))) :: multiply(listOfLists.tail) 
}

multiply( List(List(3, 4, 5, 6), List(4, 5, 6, 7, 8)) )
// res1: List[List[Int]] = List(List(-3, -4, -5, -6), List(-4, -5, -6, -7, -8))

multiply( List(List(3.0, 4.0), List(5.0, 6.0, 7.0)) )
// res2: List[List[Double]] = List(List(-3.0, -4.0), List(-5.0, -6.0, -7.0))

For more details about context bound, here's a relevant SO link.

Leo C
  • 22,006
  • 3
  • 26
  • 39
  • I didn't downvote but "you need to restrict A to be context-bound to, say, Numeric[A]" is unlikely to be very understandable to the OP given the level of Scala knowledge implied by their post. So "not (that) useful", yet. – The Archetypal Paul Nov 16 '17 at 10:17
  • @The Archetypal Paul, thanks for the comment. I would assume anyone coding Scala generics should've minimally been exposed to some concept of implicit values, context bounds, etc. Nonetheless, I've slightly revised/expanded the answer. – Leo C Nov 16 '17 at 12:44