Опциональное сцепление со струнами Swift

С необязательной цепочкой, если у меня есть переменная Swift

var s: String?

s может содержать ноль или строку, обернутую в необязательный. Итак, я попытался это получить его длину:

let count = s?.characters?.count ?? 0

Тем не менее, компилятор хочет это:

let count = s?.characters.count ?? 0

Мое понимание необязательной цепочки заключается в том, что, как только вы начнете использовать?. в точечном выражении остальные свойства становятся необязательными и обычно доступны?.не..

Итак, я вырыл немного дальше и попробовал это на детской площадке:

var s: String? = "Foo"
print(s?.characters)
// Output: Optional(Swift.String.CharacterView(_core: Swift._StringCore(_baseAddress: 0x00000001145e893f, _countAndFlags: 3, _owner: nil)))

Результат показывает, чтоs?.characters действительно необязательный экземпляр, указывающий, чтоs?.characters.count должно быть незаконным.

Может ли кто-нибудь помочь мне понять это положение вещей?

 Martin R01 авг. 2016 г., 20:08
Теперь также обсуждается на [swift-users]:lists.swift.org/pipermail/swift-users/Week-of-Mon-20160801/....
 Martin R01 авг. 2016 г., 15:29
И то и другоеs?.characters.count а также(s?.characters)?.count компилировать, но(s?.characters).count не делает. Это выглядит какcharacters.count в первом случае рассматривается как одна необязательная цепочка, но я не видел этого документально.

Ответы на вопрос(2)

В списке рассылки Swift-пользователи Инго Майер был достаточно любезен, чтобы указать мне нараздел о необязательных выражениях цепочки в спецификации языка Swift, которая гласит:

Если выражение постфикса, которое содержит выражение необязательной цепочки, вложено в другие выражения постфикса, только самое внешнее выражение возвращает необязательный тип.

Продолжаем с примера:

var c: SomeClass?
var result: Bool? = c?.property.performAction()

Это объясняет, почему компилятор хочетs? .characters.count в моем примере выше, и я считаю, что он отвечает на оригинальный вопрос. Однако, как заметил @Martin R в комментарии, все еще остается загадкой, почему эти два выражения по-разному трактуются компилятором:

s?.characters.count
(s?.characters).count

Если я читаю спецификации правильно, подвыражение

(s?.characters) 

"вложено в" общее постфиксное выражение

(s?.characters).count

и, следовательно, должны рассматриваться так же, как версия без скобок. Но это отдельная проблема.

Спасибо всем за вклад!

 ingoem01 авг. 2016 г., 22:11
Как уже говорилось в списке, в спецификации не хватает объема вопросительного знака, но я думаю, что swiftc делает правильные вещи. В языках программирования довольно распространено использование скобок для разграничения области действия всех видов операторов / ключевых слов. Это часто приводит к хорошему (я бы сказал, интуитивному) свойству, которое позволяет заменить выражения в скобках на привязки let и при этом иметь ту же семантику. Используя ваш пример,let x = s?.characters; x?.count имеет ту же семантику, что и(s?.characters)?.count что было бы не так, если(s?.characters).count был действительный код Swift.
Решение Вопроса

Когда ты сказал:

Мое понимание необязательной цепочки заключается в том, что, как только вы начнете использовать?. в точечном выражении остальные свойства становятся необязательными и обычно доступны?.не..

Я бы сказал, что вы почти у цели.

Дело не в том, что все свойства сделаны необязательными, а в том, что исходный вызов является необязательным, поэтому похоже, что другие свойства являются необязательными.

characters не является необязательным свойством и не являетсяcount, но значение, на которое вы его вызываете, не является обязательным. Если есть значение, тоcharacters а такжеcount свойства будут возвращать значение; иначе,nil возвращается Именно поэтому результатs?.characters.count возвращаетInt?.

Если любое из свойств не является обязательным, вам нужно будет добавить? к этому, но, в вашем случае, они не. Так что ты не

Отредактировано следующий комментарий

Из комментария:

Мне все еще странно, что обаs?.characters.count а также(s?.characters)?.count компилировать, но(s?.characters).count не делает. Почему существует разница между первым и последним выражением?

Я постараюсь ответить здесь, где больше места, чем в поле для комментариев:

s?.characters.count

Еслиs ноль, все выражение возвращаетnilв противном случаеInt, Таким образом, тип возвращаемого значенияInt?.

(s?.characters).count // Won’t compile

Разбить это: еслиs являетсяnil, затем(s?.characters) являетсяnilпоэтому мы не можем позвонитьcount в теме.

Для того, чтобы позвонитьcount собственность на(s?.characters)выражение необязательно должно быть развернуто, то есть записано как:

(s?.characters)?.count

Отредактировано, чтобы добавить дальше

Лучшее, что я могу объяснить, это немного кода для детской площадки:

let s: String? = "hello"

s?.characters.count
(s?.characters)?.count
(s)?.characters.count
((s)?.characters)?.count

// s?.characters.count
func method1(s: String?) -> Int? {
    guard let s = s else { return nil }

    return s.characters.count
}

// (s?.characters).count
func method2(s: String?) -> Int? {
    guard let c = s?.characters else { return nil }

    return c.count
}

method1(s)
method2(s)
 Abizern02 авг. 2016 г., 11:10
Хорошо знать. Спасибо!
 Abizern01 авг. 2016 г., 15:35
@MartinR Я пытался ответить на это в отредактированном ответе.
 Viktor Simkó01 авг. 2016 г., 15:35
В(s?.characters).count Вы пытаетесь получитьcount свойство необязательное. В первомcharacters не является обязательным.
 Martin R01 авг. 2016 г., 20:32
Ваш ответ (насколько я понимаю) поддерживается для swift-пользователей:lists.swift.org/pipermail/swift-users/Week-of-Mon-20160801/... :)
 Martin R01 авг. 2016 г., 16:01
Но нетcharacters.count имущество! Похоже что компиляторлечит это как «комбинированное свойство», но было бы неплохо иметь для этого определенную ссылку. - Почему должна быть разница междуa.b.c , (a.b).c или же((a).b).c)?
 Martin R01 авг. 2016 г., 15:23
Мне все еще странно, что обаs?.characters.count а также(s?.characters)?.count компилировать, но(s?.characters).count не делает. Почему существует разница между первым и последним выражением?
 Martin R01 авг. 2016 г., 15:38
Но разве такой же аргумент не применим в первом выражении?s?.characters имеет типInt? (и являетсяnil еслиs == nil). Почему мы можем позвонитьcount на это вs?.characters.count? Почему добавление скобок имеет значение?
 Abizern01 авг. 2016 г., 15:54
Без скобок,characters.count вызывается по развернутому значению. С круглыми скобкамиs?.characters оценивается сначала, а затемcount, посколькуs?.characters поскольку выражение является необязательным, его необходимо развернуть перед вызовомcount в теме.
 Abizern01 авг. 2016 г., 15:44
Этоs который имеет необязательный тип. После успешного развертывания вы можете связать все остальные вызовы с необязательным значением. Итак, вы звонитеcharacters.count наString если он существует или просто возвращаетсяnil если это не так. когда вы заключаете скобки в скобки, вы проверяете скобки перед вызовом внешних методов. так что вместо звонкаcharacters.count на развернутом значении вы звонитеcharacters для необязательной строки (которая является необязательной), а затем счетчик вызовов для результата, который должен быть условно развернут.
 Martin R01 авг. 2016 г., 15:47
Но в обоих случаяхcharacters вызывается на строку, а затемcount на результат. Здесь нетcharacters.count свойство, которое вы можете вызвать на строку.

Ваш ответ на вопрос