Стендап Сьогодні 📢 Канал в Telegram @stendap_sogodni

🤖🚫 AI-free content. This post is 100% written by a human, as is everything on my blog. Enjoy!

01.05.2024

Optional у Swift

Продовжуємо рубрику “аспекти дизайну мов програмування”. Сьогодні не було настрою робити щось по трекеру, тому просто виправляв скарги лінтера. Одна з частих скарг — на так званий “force unwrapping”. Про неї й хочу поговорити.

Відсутність значення у Swift реалізована механізмом Optional. Optional приймає або значення загорнутого типу, або nil. Це єдиний випадок, коли звернення до значення неприпустиме, ніякого більше “порожнього посилання” або “непризначеної змінної”. Та головне, що тип Optional обовʼязково потрібно “розгорнути”. Або безпечною перевіркою, або примусово — що може призвести до фатальної помилки.

Мене здивувало у Swift те, скільки методів в стандартній бібліотеці повертають Optional. Наприклад: методи Array.first, .last, .min, .max. Бо дійсно, якщо масив порожній, то жодних елементів в ньому не буде. (На жаль, операції з індексами позбавлені такої безпеки та можуть призвести до помилки.)

З наївним написанням умов це трохи дратує: я ж перевірив, що масив не порожній!

if !items.isEmpty {
  maxItem = items.max! // Примусово розгортаємо!
  // ... щось зробити з maxItem
}

В багатьох випадках таку непряму та тому небезпечну перевірку можна замінити на явну, безпечну:

if let maxItem = items.max {
  // ... щось зробити з maxItem
}

Можна помітити зворотний порядок гілок: я звик перевіряти if item == nil як особливий випадок, а потім вже працювати з ним; у Swift для того є альтернативна конструкція guard, яка розгортає тип без вкладення:

guard let maxItem = items.max else { return }
// ... щось зробити з maxItem

Взагалі мені дуже подобається такий підхід до відсутності значень, бо він виділяє рівно один механізм та не дозволяє просто його ігнорувати. Проте, якщо в Go надійна програма завжди здобрена перевірками if err != nil, то у Swift так само багато перевірок guard.