Быстрое уменьшение - почему значение необязательно? - PullRequest
0 голосов
/ 12 января 2019

Почему total необязательно в строке return total + 1?

return first.enumerated().reduce(0) { total, letter in
   let index = first.index(first.startIndex, offsetBy: letter.offset)
   if first[index] != second[index]{
       return total + 1
   }
   return total
}

Значение необязательного типа Int? должен быть развернут до значения type'Int 'Объединить, используя' ?? ' обеспечить по умолчанию, когда необязательный значение содержит 'nil' Force-unwrap, используя '!' отменить исполнение, если необязательное значение содержит 'nil'

Так что это исправляет:

return first.enumerated().reduce(0) { total, letter in
   let index = first.index(first.startIndex, offsetBy: letter.offset)
   if first[index] != second[index]{
       return total! + 1
   }
   return total
}

Если я разобью его, изменения произойдут при добавлении let index ....

ОК. Возвращает общее количество первых и общее число не является обязательным:

return first.reduce(0) { total, letter in
    return total + 1
}

OK - это перечисленное и общее не является обязательным:

return first.enumerated().reduce(0) { total, letter in
    return total + 1
}

ОШИБКА - Это приводит к ошибке компиляции, которая является необязательной

return first.enumerated().reduce(0) { total, letter in
    let index = first.index(first.startIndex, offsetBy: letter.offset)
    return total + 1
}

1 Ответ

0 голосов
/ 13 января 2019

Для того, чтобы вы вообще получили этот результат (насколько я могу судить), включающая функция должна возвращать Int?. Подразумевается, что reduce может возвращать необязательный. В отсутствие условия компилятор может определить, что reduce никогда не вернет nil, то есть, total никогда не будет nil. Таким образом, компилятор делает вывод, что возвращаемый тип замыкания равен Int. Компилятор, кажется, запутывает вывод типа для замыкания reduce и total. После того, как вы добавите условие, компилятор не сможет определить, вернет ли reduce ноль или нет. Теперь, когда он излишне выводит тип для total, он ошибается.

Для меня это похоже на случай, когда вывод типа Свифта сбился с пути. Очевидно, что total никогда не равен нулю на основании документации enumerated.

Если вы немного измените код, вы получите ожидаемый результат:

   return first.enumerated().reduce(0) { (total: Int, letter) in
       let index = first.index(first.startIndex, offsetBy: letter.offset)
       if first[index] != second[index]{
          return total + 1
       }
       return total
   }

Swift делает много выводов типа, и это действительно здорово, потому что я получаю строгую типизацию, сохраняя при этом многие преимущества динамического языка. Однако, по моему опыту, выводы Свифта иногда могут быть загадочными. Он легко справляется с загадочными ситуациями и натыкается на то, что мне кажется очевидным.

Для меня это похоже на ошибку.

...