Почему у Java, C # и C ++ нет диапазонов? - PullRequest
9 голосов
/ 29 января 2009

Ada , Pascal и многие другие языки поддерживают диапазоны, способ подтипов целых чисел. Диапазон - это целочисленное значение со знаком, которое варьируется от значения (первое) до другого (последнее). Легко реализовать класс, который делает то же самое в ООП, но я думаю, что встроенная поддержка этой функции может позволить компилятору выполнять дополнительные статические проверки.

Я знаю, что статически невозможно проверить, что переменная, определенная в диапазоне, не будет «переполнена» во время выполнения, т. Е. Из-за неправильного ввода, но я думаю, что что-то можно сделать. Я думаю о подходе Design by Contract (Eiffel) и Spec # ( C # Contracts ), которые дают более общее решение.

Есть ли более простое решение, которое проверяет, по крайней мере, статическое внешнее присваивание во время компиляции в C ++, C # и Java? Какой-то static-assert ?

edit : Я понимаю, что «диапазоны» могут использоваться для разных целей:

  1. итераторы
  2. счетчикам
  3. целочисленный подтип

Я бы сосредоточился на последнем, потому что формирователи легко сопоставимы на языке C *. Я имею в виду закрытый набор значений, что-то вроде громкости музыки, то есть диапазон, который варьируется от 1 до 100. Я хотел бы увеличить или уменьшить его на значение. Я хотел бы иметь ошибку компиляции в случае статического переполнения, что-то вроде:

volume=rangeInt(0,100);
volume=101;  // compile error!
volume=getIntFromInput(); // possible runtime exception

Спасибо.

Ответы [ 11 ]

4 голосов
/ 29 января 2009

Типы поддиапазонов на самом деле не очень полезны. Мы не часто размещаем массивы фиксированной длины, и также нет причин для целых чисел фиксированного размера. Обычно там, где мы видим массивы фиксированного размера, они действуют как перечисление, и у нас есть лучшее (хотя и «более тяжелое») решение для этого.

Типы поддиапазонов также усложняют систему типов. Было бы гораздо полезнее ввести ограничения между переменными, чем фиксированными константами.

(Обязательно укажите, что целые числа должны быть произвольного размера на любом разумном языке.)

3 голосов
/ 29 января 2009

Диапазоны наиболее полезны, когда вы можете сделать что-то в этом диапазоне, кратко. Это означает закрытие. По крайней мере, для Java и C ++ тип диапазона будет раздражающим по сравнению с итератором, потому что вам нужно определить внутренний класс, чтобы определить, что вы собираетесь делать в этом диапазоне.

3 голосов
/ 29 января 2009

Java имеет ключевое слово assert начиная с версии 1.4. Если вы занимаетесь программированием по контракту, вы можете использовать его для проверки правильности назначения. И любой изменяемый атрибут внутри объекта, который должен попадать в определенный диапазон, должен быть проверен перед установкой. Вы также можете вызвать исключение IllegalArgumentException.

Почему нет типа диапазона? Я предполагаю, что оригинальные дизайнеры не видели ни одного в C ++ и не считали его таким же важным, как и другие функции, которые они пытались понять.

2 голосов
/ 29 января 2009

Для C ++ в настоящее время реализуется библиотека для переменных с ограниченными значениями, которая будет предложена в библиотеках повышения: http://student.agh.edu.pl/~kawulak/constrained_value/index.html

2 голосов
/ 29 января 2009

Паскаль (а также Delphi) использует тип поддиапазона, но он ограничен порядковыми типами (целое число, символ и даже логический).

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

1 голос
/ 27 июля 2010

Это старый вопрос, но просто хотелось его обновить. В Java нет диапазонов как таковых, но если вам действительно нужна функция, вы можете использовать Commons Lang , который имеет несколько классов диапазонов, включая IntRange

IntRange ir = new IntRange(1, 10);

Странно, этого нет в Commons Math. Я частично согласен с принятым ответом, но я не считаю, что диапазоны бесполезны, особенно в тестовых случаях.

1 голос
/ 31 января 2009

Я бы добавил к ответу Тома Хоутина (на что я согласен), что для C ++ наличие диапазонов не означает, что они будут проверяться - если вы хотите быть последовательными с общим поведением языка - при доступе к массиву, для Например, также не проверяются по дальности. Я считаю, что для C # и Java решение было основано на производительности - проверка диапазонов наложила бы бремя и усложнила бы компилятор.

Обратите внимание, что диапазоны в основном полезны на этапе отладки - нарушение диапазона никогда не должно происходить в рабочем коде (теоретически). Поэтому проверки диапазона лучше осуществлять не внутри самого языка, а в предварительных и постусловиях, которые можно (следует) удалить при создании релизной сборки.

1 голос
/ 31 января 2009

Гибкость накатывать свои собственные лучше, чем встроенные в язык. Что, если вы хотите использовать насыщающую арифметику, например, вместо того, чтобы генерировать исключение для значений вне диапазона? * 1001 Т.е. *

MyRange<0,100> volume = 99;
volume += 10; // results in volume==100
1 голос
/ 29 января 2009

C ++ позволяет вам реализовывать такие типы с помощью шаблонов, и я думаю, что уже есть несколько библиотек, делающих это. Однако, я думаю, что в большинстве случаев выгода слишком мала, чтобы оправдать дополнительную сложность и штраф за скорость компиляции.

Что касается статического утверждения, оно уже существует. Boost имеет BOOST_STATIC_ASSERT, а в Windows, я думаю, библиотека ATL от Microsoft определяет аналогичную.

boost::type_traits и boost :: mpl, вероятно, ваши лучшие друзья в реализации чего-то подобного.

1 голос
/ 29 января 2009

В C # вы можете сделать это:

foreach(int i in System.Linq.Enumerable.Range(0, 10))
{
    // Do something
}
...