Несмежные диапазоны для подтипов в Аде?

Всего в качестве упражнения по изучению системы типов Ада я пытался создать 3 типа (точнее, тип и 2 подтипа):

  • Month_Type, перечисление всех месяцев
  • Short_Month_Type, подтип Month_Type, имеющий только месяцы с 30 днями
  • February_Month_Type, подтип только с февралем

Кажется, подтипы должны использовать механизм range, верно? (Есть ли какой-либо другой подтип?) Чтобы заставить его работать с непрерывными диапазонами, мне пришлось расположить перечисление Month_Type в следующем порядке:

   type Month_Type is (February, April, June, September, November, January, March, May, July, August, October, December);

Очевидно, что это не естественный порядок месяцев, и я мог видеть людей/меня, пытающихся сделать Month_Type'First или что-то еще, ожидающих получить январь.

Итак, два общих вопроса из этого глупого примера:

  1. Могу ли я иметь подтип, который указывает определенные компоненты его базового типа вместо диапазона?
  2. Могу ли я как-то скрыть детали реализации порядка, в котором я ставлю месяцы (например, сделать «Первый невидимым»)?

Спасибо!


person J Cooper    schedule 31.08.2012    source источник


Ответы (4)


Нет, перечисление подтип допускает только range_constraint в этом контексте , но вы можете создать любое количество Устанавливает с помощью Ada.Containers.Ordered_Sets< /а>. Примеры есть здесь и здесь.

person trashgod    schedule 01.09.2012
comment
Это доступно, но в нем нет необходимости, за исключением сложных случаев. - person T.E.D.; 01.09.2012
comment
Итак, вот как бы я только что подошел к вещам на других языках. Что меня заинтересовало, так это возможность использовать саму систему типов для обозначения таких вещей, как короткие месяцы, нечетные числа или что-то еще. Но спасибо, что сообщили мне, что эта функциональность не всегда возможна! - person J Cooper; 02.09.2012

Вы можете создать объект, обозначающий только определенные значения в перечислении. Обычно мы называем это «набором».

Многие языки имеют наборы в качестве базовых типов (наряду с массивами и записями). Конечно, некоторые этого не делают. Ада находится где-то посередине. Он официально не имеет типа с именем "set" или что-то в этом роде, но логические операции определены так, чтобы работать как побитовые логические операции над массивами boolean. Если вы упаковываете массив, вы получаете в точности то, что дает вам тип "set" других языков. Итак, Ada поддерживает наборы, они просто называются "массивами логических значений".

type Month_Set is array (Month) of Boolean;
Short_Month : constant Month_Set := 
    (September => true, April => true, June => true, November => true, 
     February => true, others => false);
Y_Month : constant Month_Set :=
    (January => true, February => true, May => True, July => true, 
     others => false);

-- Inclusion
if (Short_Month(X)) then ...

-- Intersection (Short_Y will include only February)
Short_Y := Short_Month and Month_Ending_in_Y;

-- Union (Short_Y will include All Short_Months and all Y_Months
Short_Y := Short_Month or Month_Ending_in_Y;

-- Negation (Short_Y will include all Short_Months not ending in Y
Shorty_Y := Short_Month and not Month_Ending_in_Y;
person T.E.D.    schedule 01.09.2012
comment
+1 за отличную альтернативу; см. также 4.5.1 Логические операторы и формы управления коротким замыканием. - person trashgod; 02.09.2012
comment
Это отличный ответ, и я не знал об Аде. Как я объяснил в другом комментарии, меня интересовала сама система типов, способная распознавать Short_Month из Y_Month, надеюсь, во время компиляции. Но, очевидно, не все, что хочется, возможно :) Еще раз спасибо. - person J Cooper; 02.09.2012

Вы можете использовать предикаты подтипа. В твоем случае:

subtype Short_Month_Type is Month_Type with
  Static_Predicate => Short_Month_Type in April | June | September | November
person castle-bravo    schedule 15.01.2018
comment
Вероятно, было бы полезно упомянуть, что предикаты подтипа были добавлены в Аде 2012 и, следовательно, не были доступны в то время, когда был задан исходный вопрос (через несколько месяцев) - person egilhh; 24.05.2021

Trashgod ответил на первый вопрос. Чтобы ответить на второй вопрос, сделайте сам тип приватным.

person Shark8    schedule 01.09.2012
comment
Да, таким образом можно раскрыть столько абстрактного типа данных, сколько имеет смысл для приложения. - person trashgod; 02.09.2012
comment
Полагаю, я плохо сформулировал это, но если я сделаю все перечисление приватным, то ни один потребитель пакета вообще не сможет его использовать, верно? Я полагаю, мне пришлось бы предоставить общедоступные функции Make_Month, если бы я хотел, чтобы они могли перебрасывать февральские числа, но не могли делать Month_Type'First? - person J Cooper; 02.09.2012
comment
Да; Еще одним преимуществом сокрытия реализации в абстрактном типе данных является то, что вы можете изменить его по мере необходимости, не обращая внимания на клиентов. Например, EnumSet в Java использует упакованный логический массив внутри для эффективности, как TED предполагает. - person trashgod; 02.09.2012