В этом фрагменте определите, почему условие с диапазоном совпадает со значением и какой текст напечатает код:
let statusCode = 404
if case 400..<500 = statusCode {
print("ошибка клиента")
} else {
print("другой результат")
}
Код напечатает ошибка клиента. Запись 400..<500 в pattern matching проверяет, входит ли statusCode в диапазон от 400 включительно до 500 исключительно.
Swift выполняет эту проверку через оператор сопоставления шаблона ~=: для диапазона он определяет, принадлежит ли значение заданному диапазону.
Pattern matching нужен для компактного описания условий, связанных со структурой или диапазоном значения. Такой подход позволяет использовать один механизм в switch и в условии if case, не дублируя сравнения вроде statusCode >= 400 && statusCode < 500.
В Swift диапазон — это не только способ создать последовательность значений. Он также может выступать шаблоном, с которым сопоставляется другое значение.
При обработке HTTP-кодов важно не перепутать границы диапазона. Код 400 должен попасть в категорию ошибок клиента, а код 500 — нет.
Если заменить полуоткрытый диапазон 400..<500 на закрытый 400...500, значение 500 будет ошибочно классифицировано как ошибка клиента. Если использовать только statusCode / 100, можно потерять точность для нестандартных кодов и усложнить условие.
Конструкция if case pattern = value пытается сопоставить значение с шаблоном. В данном случае шаблон — диапазон 400..<500, а сопоставляемое значение — целое число 404.
Для диапазона применяется оператор ~=. Концептуально проверка эквивалентна следующему условию:
Разница в том, что if case использует общий механизм сопоставления шаблонов и хорошо сочетается с другими шаблонами Swift. Оператор ..< создаёт полуоткрытый диапазон: левая граница включается, правая исключается. Поэтому 404 совпадает, 400 совпадает, а 500 — нет.
Это не приведение типа и не проверка равенства диапазона числу. Диапазон выступает шаблоном, а конкретное поведение сопоставления определяется ~= для соответствующих типов.
В сетевом клиенте нужно разделить ответы на успешные, ошибки клиента и ошибки сервера. Возможны три варианта.
Первый — цепочка сравнений:
Плюс этого решения — явность. Минус — границы и логика быстро становятся громоздкими при добавлении новых категорий.
Второй — вычисление группы через деление на 100. Это коротко для стандартных HTTP-кодов, но хуже выражает нестандартные диапазоны и отдельные исключения.
Третий — switch с диапазонами:
Для нескольких взаимоисключающих категорий выбран третий вариант: диапазоны явно показывают границы, а default обрабатывает значения вне известных интервалов. Для единственной проверки достаточно if case.
Вопрос: Включается ли правая граница в шаблон 400..<500?
Ответ: Нет. Оператор ..< создаёт полуоткрытый диапазон: 400 включён, 500 исключён. Поэтому 499 совпадает с шаблоном, а 500 — нет. Для включения обеих границ используется 400...500.
Вопрос: Чем if case 400..<500 = code отличается от обычного if code == 400..<500?
Ответ: Эти выражения имеют разный смысл и типы. Число нельзя сравнить на равенство с диапазоном: диапазон описывает множество допустимых значений, а не одно значение. if case применяет механизм pattern matching и проверяет принадлежность code диапазону через ~=.
Вопрос: Можно ли использовать собственный тип как шаблон для if case?
Ответ: Да, если для подходящих типов доступен оператор ~=. Например, можно определить собственную функцию сопоставления для шаблона и значения, после чего использовать этот шаблон в switch или if case. Это расширяет выразительность pattern matching, но требует аккуратно проектировать семантику сопоставления: результат должен быть предсказуемым, а проверка — не иметь неожидательных побочных эффектов.