pourquoi les plages Swift ne sont-elles pas comparables?

Вопрос или проблема

Почему диапазоны Swift не являются Comparable, если их элемент типа T является сопоставимым? (такими как Int, String, Double и т. д.).

Например:

let rangeFive = 1...10
let rangeSix = 1...10
rangeFive < rangeSix

ИЛИ

let rangeFive = 1...10
let rangeSix = 1...10
rangeFive <= rangeSix

ИЛИ

let rangeFive = 1...10
let rangeSix = 1...10
rangeFive == rangeSix


let minRangeFive = rangeFive.min()
let maxRangeSix = rangeSix.max()
minRangeFive < maxRangeSix


// Ошибка: Бинарный оператор '<' не может быть применен к двум 'ClosedRange<Int>.Element?' (также известный как 'Optional<Int>')

Я попробовал rangeFive == rangeSix – и это работает, но не с другими операторами сравнения. Почему так получается, что когда типы диапазонов содержат Comparable данные, все типы диапазонов не являются Comparable и не соответствуют протоколу Comparable? Сопоставимые диапазоны Swift не сопоставимы, т.е. «все типы диапазонов не сопоставимы, т.е. не соответствуют требованиям протокола Comparable», в то время как тип данных диапазона partialrangefrom, partialrangeupto, partialrangethrought<T>, где T является сопоставимым типом данных (Int, String, Double), является сопоставимым.

Сделать диапазоны сопоставимыми привело бы к большему количеству путаницы, чем стоит, потому что нет очевидно правильного ответа на вопрос, что значит, что один диапазон больше другого.

Мы можем согласиться с тем, что 1...2 определенно меньше, чем 3...4, и что 1... вероятно следует считать меньше, чем 2....

Но что насчет перекрывающихся диапазонов?

Должен ли 10...20 быть меньше, чем 10...100?

Существует несколько способов, как мы могли бы это определить, и у каждого из них есть проблемы:

  1. Диапазон a меньше диапазона b, если как его нижние, так и его верхние границы меньше верхних границ b.
  2. Диапазон a меньше диапазона b только если его нижняя граница меньше нижней границы другого
    • Это приводит к другим странным ситуациям, когда 1...10 < 2...9 будет истинным (потому что 1 < 2), но одновременно 1...10 > 2...9 также будет истинным (потому что 10 > 9).
  3. Возможно, вы могли бы определить это с точки зрения “центра” диапазона, но:
    • Это не работает для бесконечных диапазонов
    • Не работает для элементов, среднее которых нельзя вычислить. Например, какова середина диапазона "foo"..."bar"?

Равенство не имеет этой проблемы, потому что вы можете просто сравнить границы и получить однозначно правильный ответ. Именно поэтому диапазоны условно Equatable, но никогда не Comparable.

Ответ или решение

В языке Swift типы диапазонов (ranges) не соответствуют протоколу Comparable, даже если их элементы имеютComparable-свойства. Это может вызывать непонимание, особенно когда в диапазоне хранятся сравнимые типы, такие как Int, String или Double. Рассмотрим подробнее причины, по которым диапазоны не могут быть сравнены, и критерии, по которым Swift реализует свои диапазоны.

1. Проблемы с определением порядка

Одной из главных причин, по которой диапазоны не соответствуют протоколу Comparable, является отсутствие однозначного определения, как можно сравнивать диапазоны друг с другом. Например:

  • Два диапазона могут не пересекаться, что позволяет установить порядок, например, диапазон 1...2 меньше диапазона 3...4.
  • Однако, когда диапазоны перекрываются, становится сложно установить, какой из них больше. Например, диапазон 10...20 и 10...100 имеют общую границу, и сложно определить, какой из них «больше» по сравнению с другим.

2. Протокол Comparable требует строгого порядка

Протокол Comparable требует, чтобы все значения типа можно было сравнить так, чтобы для любых двух значений a и b одно из следующих условий всегда выполнялось: a < b, a == b, или a > b. В случае диапазонов с перекрывающимися значениями это требование не выполняется, так как диапазоны могут не поддаваться строгой сортировке.

3. Альтернативные определения несоответствия

Рассмотрим несколько альтернативных возможностей определения отношений между диапазонами:

  1. Сравнение по границам: Если сравнивать нижние и верхние границы диапазонов, то можно столкнуться с ситуациями, когда диапазоны конфликтуют. Например, диапазоны 1...10 и 2...9 будут по-разному относиться в зависимости от того, какая граница используется для сравнения:

    • 1...10 < 2...9 будет истинно, так как 1 < 2, но и 1...10 > 2...9 будет истинно, потому что 10 > 9.
  2. Определение по центру диапазона: Другой вариант — рассчитывать "центр" диапазона, но это сложно реализовать для бесконечных диапазонов или для строк, так как невозможно найти среднее значение, например, между "foo" и "bar".

4. Выравнивание по определению эквивалентности

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

Заключение

Таким образом, причина, по которой диапазоны в Swift не соответствуют протоколу Comparable, заключается в их сложности определения порядка и потенциальной путанице при использовании операторов сравнения. Эквивалентность (равенство) в этом контексте проще определить, так как мы можем опираться на границы диапазонов. Важно понимать это различие, чтобы избежать недоразумений при работе с диапазонами в Swift и соблюдать строгие правила языка.

Оцените материал
Добавить комментарий

Капча загружается...