Первое, что нужно понять, это то, что, хотя data
- это переменная, сам список остается неизменным. Хотя вы можете назначить новый список для data
, вы не можете изменить сам фактический список. Именно поэтому вы не можете передать список функции и изменить список. Таким образом, ваш цикл for
создает новый список с каждой итерацией.
К счастью, Scala позволяет действительно легко написать функциональный код для создания списков и других неизменяемых структур данных. Вот общий «функциональный» способ сделать то, что вы хотите:
def initList(data: List[Int]) = {
def initLoop(num: Int, buildList: List[Int]): List[Int] = num match {
case 0 => 0 :: buildList
case n => initLoop(n - 1, n :: buildList)
}
initLoop(1000, data)
}
По сути, здесь я заменил цикл for хвостовой рекурсивной функцией. При каждом вызове внутренняя функция строит новый список, беря текущий список и добавляя следующий номер, пока он не достигнет 0 и не вернет законченный список. Поскольку функция начинается с 1000 и возвращается к 0, список не нужно переворачивать.
Чтобы дать вам представление о том, как это работает, вот значения параметров внутренней функции при каждом рекурсивном вызове (хотя давайте начнем с 3 вместо 1000):
initLoop(3, data)
initLoop(2, 3 :: data)
initLoop(1, 2 :: 3 :: data)
initLoop(0, 1 :: 2 :: 3 :: data)
поэтому, когда он, наконец, достигнет 0, он вернется (при условии, что данные были пустыми)
Этот метод на самом деле быстрее, чем использование цикла for, поскольку вам не нужно переворачивать список в конце. Scala может оптимизировать хвостовые рекурсивные функции, поэтому вам не нужно беспокоиться о переполнении стека или ошибках нехватки памяти.
Существует множество других способов создания и преобразования списков, я также мог бы сделать это:
val data: List[Int] = List()
(0 to 1000).foldRight(data){ (num, buildList) => num :: buildList}
или даже просто так:
(0 to 1000).toList