Вопрос

I have just started to learn Scala.

When I was playing with an example in http://www.scala-lang.org/node/111 , I found a problem in types.

object Main extends App {
  def even(from: Int, to: Int): Vector[Int] =
    for (i <- from until to if i % 2 == 0) yield i

  Console.println(even(0, 20).getClass())
}

This does not compile with the following error.

<console>:9: error: type mismatch;
 found   : scala.collection.immutable.IndexedSeq[Int]
 required: Vector[Int]
           for (i <- from until to if i % 2 == 0) yield i
                  ^

However, without type specification of return value, It works and the class is Vector.

object Main extends App {
  def even(from: Int, to: Int) =
    for (i <- from until to if i % 2 == 0) yield i

  Console.println(even(0, 20).getClass()) // => class scala.collection.immutable.Vector
}

This seems to be contradict. Let me know what is the cause of the compile type error.

Это было полезно?

Решение

You are confusing classes with types. The type of the value yielded by the for-expression is IndexedSeq[Int], which happens to be implemented by a Vector instance. You specified in the signature that the return type must be Vector[Int], but the for-expression gives no such guarantee.

edit to add: you'll notice in the example on the website that they use the List.range method to produce the generator in the for-expression, and that's how they get a return type of List[Int]. If you use the Vector.range method (rather than the until method, which produces a Range) then you will be filtering a Vector and the compiler will infer this as the return type.

If you want to see they type of an expression or function, the REPL tells you when you define or evaluate it:

scala> def even(from: Int, to: Int) =
     |   for (i <- from until to if i % 2 == 0) yield i
even: (from: Int, to: Int)scala.collection.immutable.IndexedSeq[Int]
                       // ^ here!

Другие советы

Luigi's answer is correct, but maybe needs a bit more explanation. The runtime type is indeed Vector[Int], but the compiler doesn't know this. The for expression is equivalent to

from.until(to).filter(_%2==0)

So it creates a Range and then calls the filter method on it. As you can see in the API documentation, the filter method of Range is declared as returning an IndexedSeq.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top