#swift3 #swift-playground
#swift3 #swift-игровая площадка
Вопрос:
Я использую переменную j для печати ее конечного значения внутри блока отсрочки, как показано ниже:
func justForFun()
{
defer {let x = j; print("(x)")}
var j = 0
for i in 1...5
{
print("(i)")
j = i*2;
}
}
justForFun()
Итак, переменная j действительно считывается и печатается внутри блока defer. Тем не менее, PlayGround отображает предупреждение о том, что переменная j записывается, но никогда не читается. Есть ли способ просветить компилятор и избавиться от этого предупреждения?
Ответ №1:
Предупреждение исчезает, если объявление переменной перемещается выше defer
.
$ cat d.swift
func justForFun() {
var j = 0
defer {let x = j; print("(x)")}
for i in 1...5 {
print("(i)")
j = i*2;
}
}
justForFun()
$ swift d.swift
1
2
3
4
5
10
Хотя это не объясняет, почему появляется предупреждение, оно отвечает на вопрос, как вы можете убрать предупреждение.
Что касается просвещения компилятора, я не думаю, что вы можете это сделать. Возможно, вы захотите подать и выдать в swift.org ; см. Эту страницу о том, как сообщить об ошибке. Кажется, что static flow checker не просматривает defer
инструкции, которые, я считаю, должны. Хорошая находка.
Комментарии:
1. Есть ли способ присвоить этому ответу отметку «половина галочки», поскольку он ответил на первую часть моего вопроса? Я хотел бы преобразовать это в полную галочку, если другого ответа нет или если моя вторая часть вопроса является известной ошибкой в Swift 3.
2. Это хороший вопрос. Не голосуйте, если это вам не поможет. Вы можете дождаться ответа или попробовать форумы Swift или опубликовать отчет об ошибке и посмотреть, что говорят разработчики. Для меня это похоже на ошибку, но я не могу сказать вам наверняка.
3. Я ждал четыре дня и зарегистрировал это как ошибку на указанном вами сайте. Я полностью убежден в том, чтобы поставить вам полную галочку.
4. Надеюсь, вы найдете ответ. Это интересный случай. Если бы Swift принял правило, в котором говорилось, что область действия local распространяется от точки объявления до конца блока, тогда я бы ожидал ошибки компилятора, говорящей, что использование
j
in вdefer
блоке не входит в область действия. Тот факт, что появляется предупреждение, довольно странный.
Ответ №2:
Обходной путь
Добавление анонимного присваивания, _ =
, устраняет предупреждение:
// Swift 3.0
func justForFun()
{
defer {let x = j; print("(x)")}
var j = 0
// anonymous assignment:
_ = j
for i in 1...5
{
print("(i)")
j = i*2;
}
}
justForFun()
Комментарии:
1. Мои извинения. Я не могу понять ваш комментарий «Что касается …. камней». Пожалуйста, перефразируйте.
2. Хотя я по умолчанию не легкомыслен в SO, мне показалось, что, когда OP назвал свою функцию
justForFun()
, он задавал беззаботный тон. Но беззаботно! = сбивает с толку. Я удалил эту строку.