Инициализация переменных в Swift без var/let

Я новичок в Swift, поэтому это может показаться нубским вопросом, но я буду благодарен, если кто-то развеет сомнения, потому что я не могу найти никакого объяснения в Интернете. При использовании цикла for-in иногда переменные не были инициализированы ранее, и все же ошибки компилятора не возникает. Иногда, если я пытаюсь написать var/let перед ними, появляется сообщение об ошибке: шаблон 'let' не может отображаться вложенным в уже неизменяемый контекст

например, почему в приведенном ниже коде переменные movie и ReleaseDate не были инициализированы раньше?

class MovieArchive {
func filterByYear(year:Int, movies:Dictionary<String, Int> ) -> [String]{
    var filteredArray = [String]()
    for (movie, releaseDate) in movies {
        if year == releaseDate {
            filteredArray.append(movie)
        }
    }
    return filteredArray
}

}

var aiThemedMovies = ["Metropolis": 1927, "2001: A Space Odyssey": 1968, "Blade Runner": 1982, "War Games": 1983, "Terminator": 1984, "The Matrix": 1999, "A.I.": 2001, "Her": 2013, "Ex Machina": 2015]

var myArchive = MovieArchive()
myArchive.filterByYear(year: 2013
, movies: aiThemedMovies)

Заранее благодарю за любую помощь :)


person Anurita Srivastava    schedule 07.12.2016    source источник
comment
Пожалуйста, покажите пример, где появляется описанное вами сообщение об ошибке.   -  person Luca Angeletti    schedule 07.12.2016
comment
например, почему в приведенном ниже коде переменные movie и ReleaseDate не были инициализированы раньше? Потому что так работает язык. Возможно, вам понравится читать электронную книгу Swift, предоставленную Apple.   -  person dasdom    schedule 07.12.2016
comment
Ваш код отлично работает на моей игровой площадке.   -  person Luca Angeletti    schedule 07.12.2016
comment
@appzYourLife Сэр/мэм, код без ошибок, но если я попытаюсь написать var перед фильмом или датой выпуска, появится следующая ошибка /Переменная 'movie' никогда не изменялась; рассмотрите возможность изменения на константу 'let', и если я напишу let, возникнет ошибка шаблон let' не может появиться вложенным в уже неизменяемый контекст, и это происходит только в некоторых местах. Во многих циклах for-in он просит меня написать var. Спасибо за заботу.   -  person Anurita Srivastava    schedule 07.12.2016


Ответы (3)


Swift инициализирует movie и releaseDate с помощью let, но упрощает эту инициализацию, так что вы можете просто предположить, что они установлены на правильные переменные из movies каждый раз, когда цикл повторяется. Вот почему вам не нужно писать let перед movie и releaseDate.

Если вы пишете var перед переменной, вы можете изменить значение в массиве, на который она указывает. Если это позволено, то оно не позволит вам мутировать.

Например, если вы поместите var перед одной из переменных, этот код изменит все releaseDates на 2000:

class MovieArchive {
    func filterByYear(year:Int, movies:Dictionary<String, Int> ) -> [String]{
        var filteredArray = [String]()
        for (movie, var releaseDate) in movies {
            releaseDate = 2000
            if year == releaseDate {
                filteredArray.append(movie)
            }
        }
        return filteredArray
    }
}
person Tometoyou    schedule 07.12.2016
comment
Итак, установлена ​​ли инициализация по умолчанию для разрешения? Потому что, если я внесу изменения в переменную фильма, мне будет предложено инициализировать ее как var. Я просто запутался, когда использовать var, а когда нет. Спасибо за заботу. - person Anurita Srivastava; 07.12.2016
comment
@AnuritaSrivastava Обновил мой ответ :) - person Tometoyou; 07.12.2016
comment
Я знаю, что var используется для непостоянных переменных, поэтому ваш код работает без ошибок, когда я объявляю releaseDate в следующей строке, но если я этого не сделаю, он показывает ошибку. Почему это происходит? - person Anurita Srivastava; 07.12.2016
comment
Это потому, что если вы не мутируете releaseDate, нет смысла устанавливать его как переменную. Swift обнаруживает, что он не был мутирован, поэтому выдает ошибку с просьбой удалить var. - person Tometoyou; 08.12.2016
comment
Благодарю вас. Теперь я понял концепцию. :) - person Anurita Srivastava; 12.12.2016

Не касаясь практического использования, давайте просто поговорим о том, что синтаксически допустимо в цикле for. Это законно:

    for var i in 1...3 { // ok
        print(i)
        i = 0
    }

Это не законно:

    for let i in 1...3 { // error
        print(i)
    }

Почему? Потому что let неявно, когда вы говорите это:

    for i in 1...3 { // ok
        print(i)
    }

Вы не сказали var, поэтому i автоматически объявляется с let. Это просто способ сделать вашу жизнь проще. Не переживай, будь счастлив.

person matt    schedule 07.12.2016
comment
Извините, но мой вопрос о том, чтобы не использовать ни один из них, а также показывает ошибку, когда я пишу var. Итак, синтаксически правильно ли писать for i in 1....3 { }? - person Anurita Srivastava; 07.12.2016
comment
Я знаю, что это показывает ошибку, когда вы пишете var. Но я показал вам, как написать var и не получить ошибку. Вы не научитесь, если не будете смотреть и слушать. - person matt; 07.12.2016

(movie, releaseDate) — это кортеж переменных. Swift позволяет инициализировать сразу несколько переменных с помощью кортежей.

let (movie, releaseDate) = ("Metropolis", 1927)

Цикл for-in — это синтаксический сахар для повторного объявления этих констант для каждого элемента вашей коллекции. В этом случае let является неявным.

Есть и другие способы получить именованные константы с неявным let, например, с помощью замыкания:

class MovieArchive {
    func filterByYear(year: Int, movies: [String: Int]) -> [String] {
        return movies.filter { (movie, releaseDate) -> Bool in
            year == releaseDate
            }.map { $0.key }
    }
}

Кстати, приведенный выше пример дает те же результаты, что и ваш код.

Но кроме for-in, параметров func и замыканий, я не могу вспомнить других случаев, когда ключевое слово let/var было бы опущено в Swift 3.0.

person Cœur    schedule 07.12.2016
comment
Поэтому я просто запутался, когда использовать var, а когда нет. Например, почему мы это делаем? Спасибо за заботу. - person Anurita Srivastava; 07.12.2016
comment
@AnuritaSrivastava почти всегда использует var/let. Я могу думать только о пропуске в двух ранее описанных случаях, for-in и замыканиях. Кроме того, иногда встречаются неявные переменные/константы, такие как self, $0, errordo-catch) - person Cœur; 07.12.2016
comment
Спасибо за понимание! :) - person Anurita Srivastava; 07.12.2016