Задание 1
Среди приведенных вариантов укажите операторы, с ипользуемые для создания диапазонов
.> . .< . .> .< . < > .= > <
Задание 2
Среди приведенных выражений найдите те, которые будут корректно выполнены.
1.>5 "A"."Z" "a"."C" "1"."a" 1.<"B" 10.< A. 1.1.
1) Ошибка. Не существует оператора диапазона .>
2) Корректно
3) Ошибка. Левая граница диапазона должна быть меньше, чем правая. В UTF-таблице символов латинские заглавные идут до латинских строчных. Отношение символов друг к другу можно проверить с помощью выражения
"a">"C" // true
4) Корректно
5) Ошибка. Для создания диапазона не могут использоваться значения различных типов
6) Ошибка. Полуоткрытый оператор должен идти между или перед операндом. В данном случае оператор стоит после операнда
7) Ошибка. Строковый литерал должен идти в кавычках
8) Корректно
Задание 3
Покажите два способа создания диапазона, который содержит все целые числа от 1 до 9
Задание 4
Будет ли корректно выполнен следующий код? Как исправить код, если он работает некорректно?
var range = "a"."z" rangeTwo = "1"."y" range = rangeTwo
Ошибка. При объявлении параметра rangeTwo
не использован оператор var
. При инициализации значения rangeTwo
в range ошибки не возникнет, т.к. данные диапазоны одного типа данных.
Задание 5
Определите тип данных, которые будут иметь объявленные параметры
var range = 1.<10 var range2 = 1. var range3 = .<5 var range4 = -100.100
type(of: range) // Range<Int>Type type(of: range2) //Ошибка. Для осздания диапазона использован несуществующий оператор . type(of: range3) // PartialRangeUpTo<Int>Type type(of: range4) // ClosedRange<Int>Type
Доступ закрыт
В одной из предыдущих глав мы говорили о классификации типов данных, о таких категориях как хэшируемые ( Hashable
), сопоставимые ( Comparable
) и эквивалентные ( Equatable
). Напомню, что тип относится к определенной категории, если обеспечивает требуемый этой категорией функционал. К примеру значение хэшируемого типа должно иметь свойство hashValue
(листинг 1).
// получение хэша 12.hashValue //6713485746436704161
Последовательности ( Sequence
) и коллекции ( Collection
), которые мы рассматриваем в этой части книги — точно так же являются категориями. И некоторые типы, о которых мы будем говорить дальше, входят в эти категории. Всего существует великое множество различных категорий типов, их можно поделить по самым разным функциональным возможностям. И в ходе обучения, а оно надеюсь не будет для вас окончено вместе с окончанием книги, вы будете узнавать все новые и новые категории. А в какой-то момент даже начнете создавать их самостоятельно.
Диапазоны
— это, как говорилось ранее, не один, а целая группа типов данных. И каждый из них относится к определенным категориям. В этом разделе я хотел бы чуть подробнее рассмотреть данный вопрос, т.к., повторюсь, категория определяет функционал типа. А значит, если вы знаете, к какой категории относится данный тип, то вы знаете, где он может быть применен.
Напомню, что мы рассмотрели 5 типов данных, которые представляют диапазоны:
-
Range<T>
, например1..<5 -
ClosedRange<T>
, например1...10 -
PartialRangeUpTo<T>
, например..<10 -
PartialRangeFrom<T>
, например1... -
PartialRangeThrough<T>
, например...10
где T
— тип данных элементов диапазона
Последовательности (Sequence) и коллекции (Collection)
Начнем рассмотрение материала с категорий Sequence
и Collection
. Последовательности ( Sequence
) — это упорядоченный набор элементов, в котором есть возможность поочередного доступа к ним. Коллекции ( Collection
) основаны на последовательностях, они позволяет осуществить прямой доступ к любому элементу по его индексу.
Не все диапазоны являются последовательностями и/или коллекциями! Взгляните на листинг 2, в котором создаются два диапазона
let rangeOne = .10 type(of: rangeOne) // PartialRangeThrough<Int> let rangeTwo = .<10 type(of: rangeTwo) // PartialRangeUpTo<Int>
У данных диапазонов нет начального элемента, определена лишь верхняя граница. А значит мы вообще не можем считать их упорядоченным набором, т.к. не знаем, где именно этот набор начинается. Чтобы убедиться в этом откройте справку Xcode и найдите в ней описание типа PartialRangeThrough
(пункт меню Help — Developer Documentation), в разделе Conforms to не ни одного упоминания Sequence
и Collection
(рисунок 1).

Рисунок 1. Справка для типа PartialRangeThrough
Та же ситуация и с PartialRangeUpTo
. Он не является последовательностью, а значит и коллекцией.
С остальными типами диапазонов ситуация несколько более сложная, ни такая однозначная. Откройте справку для типа Range
и посмотрите на раздел Conforms to (рисунок 2).

Рисунок 2. Справка для типа Range
Обратите внимание на примечание к Sequence
и Collections
: Conforms when Bound conforms to Strideable and Bound. Stride conforms to SignedInteger
. Оно определяет условие, при котором значение данного типа является последовательностью и коллекцией. Если внимательно прочитать данное примечание, то становится понятно, что отношение к последовательности и коллекции зависит от типа данных элементов диапазона, а если точнее, то его верхней и нижней границы. Другими словами, читая дословно, значение типа Range
тогда является последовательностью, когда его границы имеют такой тип данных, который входит в категорию Strideable
(и еще одно условие про Bound.Stride
, но пока его опустим).
Таким образом значение типа Range<Int>
является Sequence
и Collections
, а вот Range<String>
не является таковым. Подобное актуально в том числе для типа ClosedRange<T>
.

Рисунок 3. Справочное окно для PartialRangeFrom
При этом стоит быть очень аккуратным. Раз это последовательность, то мы можем поочередно перебирать ее элементы (как это делать, вы узнаете уже скоро). Но представьте следующую ситуацию: Вы работаете с диапазоном типа PartialRangeFrom<UInt8>
(листинг 3).
var range = UInt8. type(of: range) // PartialRangeFrom<UInt8>Type UInt8.max // максимальное значение типа - 255
Вы доходите до значения 255 в данном диапазоне и хотите взять следующее. Так как диапазон не ограничен справа, то вы вполне можете попытаться сделать это. Но при попытке получите сообщение об ошибке, т.к. 256 выходит за рамки возможностей UInt8
.
Именно по этой причине нужно всегда быть осторожным, работая с диапазонами.
Хэшируемые диапазоны (Hashable)
Диапазоны, ограниченные с обеих сторон, являются хэшируемыми, т.е. они соответствуют требованиям протокола Hashable
и для них возможно получить значение свойства hashValue
(листинг 4).
var range = 1.10 range.hashValue // 1819967165199576418 var range2 = 1.<10 range2.hashValue // 1819967165199576418
Причем, интересным является тот факт, что хэш высчитывается исходя только из первого и последнего элементов диапазона. Как видно в листинге 4, два диапазона, созданные с помощью различных операторов, но имеющие одни и те же пределы, имеют один и тот же хэш.
Эквивалентные диапазоны (Equatable)
Диапазоны, ограниченные с двух сторон, соответствуют протоколу Equatable
, а значит могут быть проверены на эквивалентность (листинг 5).
var range = 1.10 var range2 = 1.10 range == range2 // true
Сопоставимые диапазоны (Comparable)
Все типы диапазонов не являются сопоставимыми, т.е. не соответствуют требованиям протокола Comparable
, а значит не могут быть сопоставлены. Попытка их сравнения с помощью операторов <=
, <
, >
, >=
приведет к ошибке (листинг 6).
var range = 1.10 var range2 = 1.10 range < range2 // Ошибка
Важно, чтобы вы помнили, что диапазоны — это точно такие же значения, как и любые другие, рассмотренные нами ранее. Допустимые операции можно производить только между диапазонами одного типа данных. Так, к примеру, при попытке сравнения диапазонов различного типа произойдет ошибка (листинг 7).
var range = 1.10 type(of: range) // ClosedRange<Int> var range2 = 1.<10 type(of: range2) // Range<Int> range == range2 // Ошибка
Вы не должны знать наизусть все, о чем мы говорили. Программирование — это такой зверь, в котором важнее понимать и знать где найти. Именно этого и хотел я добиться. Важно, что вы получили практику работы со справочной документацией и в очередной раз повторили, что такое категории типов данных.




