Нумерованный тип

редактировать
именованный набор значений типа данных

В компьютерном программировании перечислимый тип (также называемый перечислением, перечислением или фактором в языке программирования R и категориальной переменной в статистике) - это тип данных, состоящий из набора именованных значений, называемых элементами, членами, перечислителями или перечислителями типа. Имена перечислителей обычно являются идентификаторами, которые в языке ведут себя как константы. Перечислимый тип можно рассматривать как вырожденное помеченное объединение из типа единицы. Переменной , которая была объявлена ​​ как имеющая перечислимый тип, можно присвоить любой из перечислителей в качестве значения. Другими словами, перечислимый тип имеет значения, которые отличаются друг от друга, которые можно сравнивать и назначать, но программист не указывает, что они имеют какое-либо конкретное конкретное представление в памяти компьютера; компиляторы и интерпретаторы могут представлять их произвольно.

Например, четыре масти в колоде игральных карт могут быть четырьмя счетчиками с именами Club, Diamond, Heart и Spade, принадлежащими перечисляемому типу с именем масть. Если переменная V объявляется с костюмом в качестве типа данных, ей можно присвоить любое из этих четырех значений.

Хотя перечислители обычно различны, в некоторых языках один и тот же перечислитель может быть указан дважды в объявлении типа. Имена счетчиков не обязательно должны быть семантически полными или совместимыми в любом смысле. Например, перечислимый тип, называемый цветом, может быть определен как состоящий из перечислителей Red, Green, Zebra, Missing и Bacon. В некоторых языках объявление перечислимого типа также намеренно определяет порядок его членов; в других счетчики неупорядочены; в других случаях неявное упорядочивание возникает из-за того, что компилятор конкретно представляет счетчики как целые числа.

Некоторые типы перечислителей могут быть встроены в язык. Логический тип, например, часто представляет собой заранее определенное перечисление значений False и True. Многие языки позволяют пользователям определять новые перечисляемые типы.

Значения и переменные перечислимого типа обычно реализуются как битовые строки фиксированной длины, часто в формате и размере, совместимых с некоторым типом целочисленным. Некоторые языки, особенно языки системного программирования, позволяют пользователю определять битовую комбинацию, которая будет использоваться для каждого перечислителя. В теории типов перечислимые типы часто рассматриваются как помеченные объединения из типов единиц. Поскольку такие типы имеют форму 1 + 1 + ⋯ + 1 {\ displaystyle 1 + 1 + \ cdots +1}1 + 1 + \ cdots + 1 , они также могут быть записаны как натуральные числа.

Содержание

  • 1 Обоснование
  • 2 Условные обозначения
  • 3 Синтаксис в нескольких языках программирования
    • 3.1 Паскаль и синтаксически похожие языки
      • 3.1.1 Паскаль
      • 3.1.2 Ада
    • 3.2 C и синтаксически похожие языки
      • 3.2.1 C
      • 3.2.2 C #
      • 3.2.3 C ++
      • 3.2.4 Go
      • 3.2.5 Java
      • 3.2.6 Perl
      • 3.2.7 Raku
      • 3.2.8 Rust
      • 3.2.9 Swift
      • 3.2.10 TypeScript
    • 3.3 Python
    • 3.4 Fortran
    • 3.5 Visual Basic / VBA
    • 3.6 Lisp
  • 4 Алгебраический тип данных в функциональном программировании
  • 5 Базы данных
  • 6 Схема XML
  • 7 См. Также
  • 8 Ссылки
  • 9 Внешние ссылки

Обоснование

Некоторые ранние языки программирования изначально не имели перечислимых типов. Если бы программист хотел, чтобы переменная, например myColor, имела значение red, переменная red должна быть объявлена ​​и ей присвоено произвольное значение, обычно целочисленная константа. Затем переменная red будет присвоена myColor. Другие методы присваивают произвольные значения строкам, содержащим имена счетчиков.

Эти произвольные значения иногда назывались магическими числами, поскольку часто не было объяснения того, как числа были получены или были ли их фактические значения значимыми. Эти магические числа могут усложнить понимание и поддержку исходного кода.

Нумерованные типы, напротив, делают код более самодокументируемым. В зависимости от языка компилятор может автоматически присваивать счетчикам значения по умолчанию, тем самым скрывая ненужные детали от программиста. Эти значения могут быть даже не видны программисту (см. скрытие информации ). Перечислимые типы также могут помешать программисту писать нелогичный код, такой как выполнение математических операций над значениями перечислителей. Если значение переменной, которой был назначен перечислитель, должно было быть напечатано, некоторые языки программирования могли также печатать имя перечислителя, а не его базовое числовое значение. Еще одним преимуществом является то, что перечисляемые типы могут позволить компиляторам обеспечивать семантическую корректность. Например:. myColor = TRIANGLE. может быть запрещено, в то время как. myColor = RED. допускается, даже если ТРЕУГОЛЬНИК и КРАСНЫЙ оба представлены внутри как 1.

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

Соглашения

Языки программирования, как правило, имеют свои собственные, часто множественные, стили программирования и соглашения об именах. Перечисления часто следуют соглашению о PascalCase или верхнем регистре, тогда как нижний регистр и другие встречаются реже.

Синтаксис в нескольких языках программирования

Паскаль и синтаксически похожие языки

Паскаль

В Паскале перечислимый тип может быть неявно объявлено перечислением значений в списке в скобках:

var suit: (трефы, бубны, червы, пики);

Объявление часто появляется в объявлении синонима типа, так что его можно использовать для нескольких переменных:

type carduit = (трефы, бубны, червы, пики); card = рекордная масть: карточный костюм; значение: 1.. 13; конец; var hand: array [1..13] карты; козырная: карточный костюм;

Порядок, в котором указаны значения перечисления, имеет значение. Перечислимый тип - это порядковый тип, и функции predи succбудут давать предыдущее или следующее значение перечисления, а ordможет преобразовывать значения перечисления в их целочисленное представление. Однако стандартный Паскаль не предлагает преобразования арифметических типов в перечисления. Extended Pascal предлагает эту функциональность через расширенную функцию succ. Некоторые другие диалекты Паскаля позволяют это через приведение типов. Некоторые современные потомки Паскаля, такие как Modula-3, предоставляют специальный синтаксис преобразования с использованием метода, называемого VAL; Modula-3 также обрабатывает BOOLEANи CHARкак специальные предопределенные перечислимые типы и использует ORDи VALдля стандартного ASCII. декодирование и кодирование.

Языки стиля Паскаль также позволяют использовать перечисление в качестве индекса массива:

var suitcount: array [carduit] of integer;

Ада

В Аде использование "=" было заменено на "есть", оставив определение очень похожее:

тип Карточный костюм (трефы, бубны, червы, лопаты);

В дополнение к Pred, Succ, Valи PosAda также поддерживает простые преобразования строк через Imageи Значение.

Подобно языкам C-стиля, Ada позволяет указывать внутреннее представление перечисления:

для использования карточных костюмов (трефы =>1, ромбы =>2, червы =>4, пики =>8);

В отличие от языков C-стиля, Ada также позволяет указывать количество бит перечисления:

для Cardsuit'Size используйте 4; - 4 бита

Кроме того, можно использовать перечисления в качестве индексов для массивов, как в Паскале, но для перечислений определены атрибуты

Shuffle: постоянный массив (Cardsuit) Cardsuit: = (Clubs =>Cardsuit'Succ (Клубы), - см. Атрибуты перечислений 'First,' Last, 'Succ,' Pred Diamonds =>Hearts, - явное значение Hearts =>Cardsuit'Last, --first значение перечисления типа Cardsuit, например, трефы Spades =>Cardsuit'First - последнее значение перечисления типа Cardsuit (например, пики);

Подобно Modula-3 Ада рассматривает Booleanи Characterкак специальные предопределенные (в пакете «Standard») перечислимые типы.. В отличие от Modula-3 можно также определять собственные типы символов:

type Cards - ('7', '8', '9', 'J', 'Q', 'K', 'A');

C и синтаксически похожие языки

C

Исходный диалект KR языка программирования C не имел перечислимых типов. В C перечисления создаются посредством явных определений (ключевое слово enumсамо по себе не вызывает выделения памяти), которые используют ключевое слово enumи напоминают struct и union определения:

enum carduit {трефы, бубны, сердца, пики}; struct card {enum carduit масть; короткое значение int; } рука [13]; enum carduit trump;

C предоставляет целочисленное представление значений перечисления непосредственно программисту. Целые числа и значения перечисления можно свободно смешивать, и все арифметические операции над значениями перечисления разрешены. Переменная enum даже может содержать целое число, которое не представляет ни одно из значений перечисления. Фактически, в соответствии с определением языка, приведенный выше код будет определять Clubs, Diamonds, Heartsи Spadesкак константы типа int, который будет преобразован (незаметно) в enum carduit, только если они сохранены в переменной этого типа.

C также позволяет программисту явно выбирать значения констант перечисления, даже без типа. Например,

enum carduit {Clubs = 1, Diamonds = 2, Hearts = 4, Spades = 8};

можно использовать для определения типа, который позволяет математическим наборам мастей быть представленными как enum carduitс помощью побитовых логических операций.

C #

Перечислимые типы в языке программирования C # сохраняют большую часть семантики «малых целых чисел» перечислений C. Некоторые арифметические операции не определены для перечислений, но значение перечисления может быть явно преобразовано в целое число и обратно, а переменная перечисления может иметь значения, которые не были объявлены определением перечисления. Например, дано

enum Cardsuit {трефы, бубны, пики, сердца};

выражения CardSuit.Diamonds + 1и CardSuit.Hearts - CardSuit.Clubsразрешены напрямую (потому что может иметь смысл переходить по последовательности значений или спрашивать, сколько шаги находятся между двумя значениями), но CardSuit.Hearts * CardSuit.Spadesсчитается менее понятным и разрешается только в том случае, если значения сначала преобразуются в целые числа.

C # также предоставляет C-подобную функцию, позволяющую определять конкретные целочисленные значения для перечислений. Таким образом можно выполнять бинарные операции с перечислениями, таким образом обрабатывая значения перечисления как наборы флагов. Эти флаги можно проверить с помощью бинарных операций или с помощью встроенного метода HasFlag типа Enum.

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

C ++

C ++ имеет типы перечисления, которые напрямую унаследованы от C и работают в основном так же, за исключением того, что перечисление является реальным типом в C ++, что дает дополнительную проверку во время компиляции. Также (как и в случае со структурами) ключевое слово C ++ enumавтоматически комбинируется с typedef, так что вместо наименования типа enum nameпросто назовите его имя. Это можно смоделировать в C с помощью typedef: typedef enum {Value1, Value2} name;

C ++ 11 предоставляет второй типобезопасный тип перечисления, который неявно не преобразуется в целочисленный тип.. Это позволяет определить потоковую передачу io для этого типа. Кроме того, перечисления не просачиваются, поэтому их нужно использовать с Enumeration Type :: enumeration. Это указывается фразой «enum class». Например:

enum class Color {Красный, Зеленый, Синий};

Базовый тип - это определяемый реализацией интегральный тип, который достаточно велик, чтобы содержать все перечисленные значения (это не обязательно должен быть наименьший из возможных типов!). В C ++ вы можете напрямую указать базовый тип. Это позволяет выполнять «предварительные объявления» перечислений:

enum class Color: long {Red, Green, Blue}; // должен соответствовать по размеру и разметке памяти типу long enum class Shapes: char; // предварительное объявление. Если позже будут определены значения, которые не вписываются в 'char', это будет ошибкой.

Go

Go использует ключевое слово iotaдля создания нумерованных констант.

type ByteSize float64 const (_ = iota // игнорирует первое значение, присваивая пустому идентификатору KB ByteSize = 1 << (10 * iota) MB GB)

Java

Версия 5.0 J2SE языка программирования Java добавила перечисляемые типы, синтаксис объявления которых аналогичен синтаксису объявления C :

enum Cardsuit {CLUBS, DIAMONDS, SPADES, HEARTS};... Cardsuit trump;

Система типов Java, однако, рассматривает перечисления как тип, отдельный от целых чисел, и смешивание значений перечисления и целочисленных значений не допускается. Фактически, тип перечисления в Java на самом деле является специальным генерируемым компилятором class, а не арифметический тип, и значения перечисления ведут себя как глобальные предварительно сгенерированные экземпляры этого класса.Типы перечислений могут иметь методы экземпляра и конструктор (аргументы которых могут быть указаны отдельно для каждого значения перечисления). Все типы перечислений неявно расширяют абстрактный класс Enum . Тип перечисления не может быть создан. ctly.

Внутри каждое значение перечисления содержит целое число, соответствующее порядку, в котором они объявлены в исходном коде, начиная с 0. Программист не может установить собственное целое число для значения перечисления напрямую, кроме одного. может определять перегруженные конструкторы, которые затем могут присваивать произвольные значения самоопределенным членам класса перечисления. Определение геттеров позволяет затем получить доступ к этим самоопределенным членам. Внутреннее целое число может быть получено из значения перечисления с помощью метода ordinal() , а список значений перечисления типа перечисления может быть получен по порядку с использованием значений ()метод. Обычно программистам не рекомендуется преобразовывать перечисления в целые числа и наоборот. Перечислимые типы: Comparableс использованием внутреннего целого числа; в результате их можно отсортировать.

Стандартная библиотека Java предоставляет служебные классы для использования с перечислениями. Класс EnumSet реализует Setзначений перечисления; он реализован как битовый массив , что делает его очень компактным и таким же эффективным, как явное манипулирование битами, но более безопасным. Класс EnumMap реализует Mapзначений перечисления для объекта. Он реализован в виде массива, в котором целочисленное значение значения перечисления служит индексом.

Perl

Языки с динамической типизацией в синтаксической традиции C (например, Perl или JavaScript ), как правило, не предоставляют перечисления. Но в программировании на Perl тот же результат может быть получен с сокращением strings list и hashes (возможно, срезов ):

my @enum = qw (трефы, бубны, червы, пики); мой (% set1,% set2); @ set1 {@enum} = (); # все очищено @ set2 {@enum} = (1) x @enum; # все установлено в 1 $ set1 {Clubs}... # false $ set2 {Diamonds}... # true

Raku

Raku действительно обеспечивает перечисления. Существует несколько способов объявления перечислений в Raku, каждый из которых создает внутреннюю карту.

перечисление Cat ; # Использование "кавычек"
enum Cat ('sphynx', 'siamese', 'bengal', 'shorthair', 'other'); # Использование списка
enum Cat (sphynx =>0, siamese =>1, bengal =>2, shorthair =>3, other =>4); # Использование конструкторов Pair
enum Cat (: sphynx (0),: siamese (1),: bengal (2), shorthair (3),: other (4)); # Другой способ использования пар, вы также можете использовать `: 0sphynx`

Rust

Хотя Rust использует ключевое слово enum, как и C, он использует его для описания помеченных объединений, перечисления которого можно рассматривать как вырожденную форму. Таким образом, перечисления Rust гораздо более гибкие и могут содержать варианты структур и кортежей.

enum Message {Quit, Move {x: i32, y: i32}, // struct Write (String), // одноэлементный кортеж ChangeColor (i32, i32, i32), // трехэлементный кортеж}

Swift

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

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

В Swift перечисления - это первоклассный тип. Они используют многие функции, традиционно поддерживаемые только классами, такие как вычисляемые свойства для предоставления дополнительной информации о текущем значении перечисления и методы экземпляра для обеспечения функциональности, связанной со значениями, которые представляет перечисление. Перечисления также могут определять инициализаторы для предоставления начального значения case и могут быть расширены для расширения их функциональности за пределы их исходной реализации; и может соответствовать протоколам для обеспечения стандартной функциональности.

enum CardSuit {регистр клубов, ромбов, червей, пиков}

В отличие от C и Objective-C, кейсам перечисления Swift не присваивается целочисленное значение по умолчанию при их создании. В приведенном выше примере CardSuit трефы, бубны, червы и пики неявно равны 0, 1, 2 и 3. Вместо этого различные варианты перечисления являются полноценными значениями сами по себе с явно определенным типом CardSuit..

В одной строке может быть несколько вариантов, разделенных запятыми:

enum CardSuit {регистры трефы, бубны, червы, пики}

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

Например, когда целые числа используются для необработанных значений, неявное значение для каждого случая на единицу больше, чем в предыдущем случае. Если в первом случае не задано значение, его значение равно 0.

Перечисление ниже является уточнением предыдущего перечисления Planet с целыми необработанными значениями для представления порядка каждой планеты от солнца:

enum Planet: Int {case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune}

В приведенном выше примере Planet.mercury имеет явное необработанное значение 1, Planet.venus имеет неявное исходное значение 2 и так далее.

«Подробности можно найти в документации по Swift здесь.»

TypeScript

Полезным дополнением к стандартному набору типов данных из JavaScript является «enum». Подобно таким языкам, как C #, перечисление - это способ дать более понятные имена наборам числовых значений.

enum Cardsuit {трефы, бубны, сердца, пики}; var c: Cardsuit = Карточный костюм. Бриллианты;

По умолчанию перечисления начинают нумерацию своих элементов, начиная с 0. Это можно изменить, вручную установив значение одного из его элементов. Например, предыдущий пример может начинаться с 1 вместо 0:

enum Cardsuit {Clubs = 1, Diamonds, Hearts, Spades}; var c: Cardsuit = Карточный костюм. Бриллианты;

Или даже вручную установить все значения в перечислении:

enum Cardsuit {Clubs = 1, Diamonds = 2, Hearts = 4, Spades = 8}; var c: Cardsuit = Карточный костюм. Бриллианты;

Удобная функция перечислений в TypeScript заключается в том, что вы также можете перейти от числового значения к имени этого значения в перечислении. Например, если представлено значение 2, но нет уверенности, что оно сопоставлено в перечислении, можно найти соответствующее имя:

enum Cardsuit {Clubs = 1, Diamonds, Hearts, Spades}; var suitName: string = Карточный костюм [2]; оповещение (имя костюма);

Python

Модуль enum был добавлен в стандартную библиотеку Python в версии 3.4.

из enum import Enum class Cards (Enum): club = 1 ромб = 2 червы = 3 пики = 4

Также существует функциональный API для создания перечислений с автоматически сгенерированными индексами (начиная с одного):

Cards = Enum («Карты», ["трефы", "бубны", "червы", "пики"])

Перечисления Python не обеспечивают семантическую корректность (бессмысленное сравнение с несовместимым перечислением всегда возвращает False, а не вызывает TypeError):

>>>Color = Enum («Цвет», [«красный», «зеленый», «синий»])>>>Shape = Enum («Форма», [«круг», «треугольник», «квадрат», «шестиугольник» "])>>>def has_vertices (shape):... return shape! = Shape.circle...>>>has_vertices (Color.green) True

Fortran

Fortran имеет только перечисляемые типы для взаимодействия с C; следовательно, семантика аналогична C и, как и в C, значения перечисления являются просто целыми числами, и никакая дополнительная проверка типа не выполняется. Приведенный выше пример C может быть записан в Fortran как

enum, bind (C) enumerator :: CLUBS = 1, DIAMONDS = 2, HEARTS = 4, SPADES = 8 end enum

Visual Basic / VBA

Перечисляемым типам данных в Visual Basic (до версии 6) и VBA автоматически назначается тип данных «Long», а также они сами становятся типом данных:

'Начинается с нуля Enum CardSuit Clubs Diamonds Hearts Spades End Enum Sub EnumExample () Dim suit As CardSuit suit = Diamonds MsgBox suit End Sub

Пример кода в VB.NET

Enum CardSuit Clubs Diamonds Hearts Spades End Enum Sub EnumExample () Dimsuit As CardSuit suit = CardSuit.Diamonds MessageBox.show (suit) End Sub

.

Lisp

Common Lisp использует спецификатор типа члена, например,

(deftype carduit () '(член клуба Diamond Heart Spade))

, в котором указано, что объект относится к типу carduit, если он #' eqlto club, diamond, heart or spade. Однако спецификатор типа члена недопустим в качестве специалиста параметра Common Lisp Object System (CLOS). Вместо этого можно использовать (атом eql), что эквивалентно (атом-член)(то есть, только один член набора может быть указан с помощью спецификатора типа eql, однако его можно использовать в качестве специалиста параметра CLOS.) Другими словами, чтобы определить методы, охватывающие перечислимый тип, метод должен быть определен для каждого конкретного элемента этого типа.

Кроме того,

(deftype Finder-element-Set-type (rest elements) `(member, @ elements))

может использоваться для определения произвольных перечислимых типов во время выполнения. Например,

(клубное алмазное сердце-лопата с набором конечных элементов)

будет относиться к типу, эквивалентному предыдущему определению кард-костюма, поскольку, конечно, просто использовалось бы

(алмазное сердце члена клуба spade)

, но может быть менее запутанным с функцией # 'memberпо стилистическим причинам.

Алгебраический тип данных в функциональном программировании

В языках функционального программирования в родословной ML (например, Standard ML ( SML), OCaml и Haskell ), для реализации перечислимого типа можно использовать алгебраический тип данных только с конструкторами с нулевым значением. Например (в синтаксисе подписей SML):

тип данных carduit = Clubs | Бриллианты | Сердечки | Тип карты пик = {масть: кардный костюм; value: int} val hand: card list val trump: carduit

В этих языках малое целое представление полностью скрыто от программиста, если такое представление действительно используется реализацией. Однако в Haskell есть класс типа Enum, который тип может наследовать или реализовать, чтобы получить сопоставление между типом и Int.

базами данных

Некоторые базы данных напрямую поддерживают перечислимые типы. MySQL предоставляет перечислимый тип ENUMс допустимыми значениями, указанными в виде строк при создании таблицы. Значения сохраняются как числовые индексы, при этом пустая строка хранится как 0, первое строковое значение хранится как 1, второе строковое значение сохраняется как 2 и т. Д. Значения могут быть сохранены и извлечены как числовые индексы или строковые значения.

Схема XML

Схема XML поддерживает нумерованные типы через фасет перечисления, используемый для ограничения большинства примитивных типов данных, таких как строки.

См. Также

Ссылки

Внешние ссылки

В Викибуке Программирование на языке Ada есть страница по теме: Перечисление
Последняя правка сделана 2021-05-19 11:39:24
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте