2015-10-13 3 views
1

Следующий код показывает ошибку несоответствия типов:Scala: индексированная Seq вместо списка в цикле

def f(arr:List[Int]): List[Int] = 
    for(num <- 0 to arr.length-1; if num % 2 == 1) yield arr(num) 

Он говорит, что он нашел IndexedSeq вместо List. Следующие работы:

def f(arr:List[Int]): List[Int] = 
    for(num <- (0 to arr.length-1).toList; if num % 2 == 1) yield arr(num) 

я использовал i <- a to b в цикле раньше, но не видел эту ошибку раньше. Может кто-то объяснить, почему формат i <- a to b здесь не может быть использован?

ответ

2

, потому что 0 to arr.length-1 Тип возврата: IndexedSeq[Int], поэтому при выполнении for yield он также даст результат с IndexedSeq[Int] типа.

Правильная функция определения:

def f(arr:List[Int]):IndexedSeq[Int] = for(num <- 0 to arr.length-1 if num%2==1) yield arr(num) 

И

for(num <- 0 to arr.length-1 if num%2==1) yield arr(num) 

будет переводить:

scala> def f(arr:List[Int]) = (0 to arr.length-1).filter(i => i%2==1).map(i => arr(i)) 
f: (arr: List[Int])scala.collection.immutable.IndexedSeq[Int] 

Таким образом, мы можем видеть, тип возвращаемого значения определяется по 0 to arr.length-1 типа.

и (0 to arr.length-1).toList меняет тип возврата IndexedSeq[int] к List[Int] типа, так for yield будет генерировать результат с типом List[Int].

+0

Вы можете пропустить точку с запятой. 'for (num <- 0 to arr.length-1 if num% 2 == 1) yield arr (num)' –

+0

Удалено, спасибо, @TheArchetypalPaul – chengpohi

1

В Скале for является syntax sugar, где:

for (i <- a to b) yield func(i) 

перевести:

RichInt(a).to(b).map({ i => func(i) }) 

RichInt.to возвращает Range

Range.map возвращает IndexedSeq

+0

Хорошо, но мой вопрос был, (NUM <- 0 в arr.length-1, если num% 2 == 1) yield arr (num), должен работать правильно? .. но это не так (по хакерранку по крайней мере). Почему? –

+0

работает, но его тип возврата - 'IndexedSeq', который не соответствует объявлению вашей функции. –

+0

О да, ладно. Спасибо –

1

В Scala для каждой итерации цикла for выход генерирует значение, которое будет запомнено. Тип возвращаемой коллекции - это тот же тип, что и итерация по, поэтому List дает список, IndexedSeq дает IndexedSeq и т. Д.

Тип (0 to arr.length-1) is scala.collection.immutable.Range, наследуемый с scala.collection.immutable.IndexedSeq[Int]. Таким образом, в первом случае результатом является IndexedSeq[Int], но возвращаемый тип функции f равен List[Int], очевидно, что он не работает. Во втором случае List дает список, а тип возврата f - List[Int].

Вы также можете написать функцию f следующим образом:

def f(arr: List[Int]): IndexedSeq[Int] = for(a <- 1 to arr.length-1; if a % 2 == 1) yield arr(a) 

Другой пример:

scala> for (i <- 1 to 5) yield i 
res0: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 3, 4, 5) 

scala> for (e <- Array(1, 2, 3, 4, 5)) yield e 
res1: Array[Int] = Array(1, 2, 3, 4, 5) 
Смежные вопросы