You can also enter variables of any type into the program that do not match any of the standard types. Such a type is specified by an enumeration of values ​​when declaring the type; the variable can take any of these values of this type, announced later in the program. General form of enumerated type description:

type nm = (word1, word2, …, wordN) ; var w: nm;

here nm is a type identifier (arbitrary), word1, word2... are specific values ​​that the variable w, belonging to type nm, can take. Values ​​of this type are considered ordered, i.e. the type description simultaneously introduces the ordering of word1< word2 < wordN. Порядковые значения отсчитываются с 0.

You can use the ord, pred, succ functions and the inc and dec procedures on enumeration type variables.

Relational operations are applicable to all variables of the same scalar type: =,<>, <=, >=, <, >.

A special feature of enumeration type variables is that their values ​​cannot be entered from the keyboard and displayed on the screen (but can be used when working with typed files).

Example 1. type color = (red, yellow, green, blue);
Here it is defined that red< yellow < green < blue. Переменная типа color может принимать одно из перечисленных значений.

Function succ(x)

Given an element x, the ordered sequence to which x belongs is determined, and the element following x in this sequence is returned.

Example 2. Let a sequence of letters be given in alphabetical order. Then succ(A) is B; succ(L) is M, etc.

For example 1 succ(red) is yellow.

function pred(x)

Given an element x, the sequence to which x belongs is determined, and the previous element of this sequence is returned.

Example 3. pred(F) is E; pred(Z) is Y, etc.

Function ord(x)

The number of element x in the sequence is given.

Example 4: ord(red) is 0 and ord(green) is 2.

Enumerated types

Enumerated types define ordered sets of values ​​by listing identifiers that represent those values. Their order follows from the sequence in which they were listed.

Syntax

type name = (id, id, ..., id);

Notes

Identifiers in the type definition become constants of the enumerated type.

The first constant has serial number 0, the second - 1, and so on.

Enum types are a subclass ordinal types.

Example

type Suit = (Clubs, Diamonds, Hearts, Spades);

When declared this way, Hearts is a constant of type Suit.

The standard Ord function returns the ordinal number of an enumerated constant. In this example,

Ord(Clubs) = 0
Ord(Diamonds) = 1
Ord(Hearts) = 2

Ada

type Day is (Mon, Tue, Wed, Thu, Fri, Sat, Sun);
type Suit is (Clubs, Diamonds, Hearts, Spades);
type Color is (White, Red, Yellow, Green, Blue, Brown, Black);
type Light is (Red, Amber, Green); -- Red and Green are overloaded

Unlike Borland Pascal, identifiers in a type definition become functions rather than constants. This allows them to be overloaded. Otherwise, the behavior of these functions is completely similar to constants.

An enumerated type is defined as a set of identifiers that, in language terms, have the same role as regular named constants, but are associated with that type. Classic description An enumeration type in Pascal looks like this:

type Cardsuit = (clubs, diamonds, hearts, spades);

Here the Cardsuit data type is declared, the values ​​of which can be any of the four listed constants. A Cardsuit type variable can take one of the values ​​clubs, diamonds, hearts, spades; it is allowed to compare enumeration type values ​​for equality or inequality, as well as use them in selection operators (in Pascal - case) as values ​​identifying options.

Using enumerations allows you to do source codes programs are more readable, since they allow you to replace "magic numbers", encoding certain values, to readable names.

Based on enumerations, some languages ​​can create set types. In such cases, a set is understood (and described) as an unordered collection of unique values ​​of an enumeration type.

An enumerated type can be used in declarations of variables and formal parameters of functions (procedures, methods). Values ​​of an enumerated type can be assigned to corresponding variables and passed through parameters of the corresponding types to functions. In addition, equality and inequality comparisons of enum type values ​​are always supported. Some languages ​​also support other comparison operations for values ​​of enumerated types. The result of comparing two enumerated values ​​in such cases is determined, as a rule, by the order of these values ​​in the type declaration - the value that occurs earlier in the type declaration is considered “less than” the value that occurs later. Sometimes an enum type or some range of values ​​of an enum type can also be used as an index type for an array. In this case, there is one element in the array for each value in the selected range, and the actual order of the elements corresponds to the order of the values ​​in the type declaration.

Implementation

Typically, enumeration values ​​are represented using integers during compilation. Depending on the specific programming language, such a representation can either be completely hidden from the programmer, or accessible to him using certain “workarounds” (for example, forcing a conversion of an enumeration value to an integer value), or even controlled by the programmer ( in such cases, the programmer has the opportunity to explicitly specify with which numbers all or some values ​​of the enumeration type will be encoded). All options have their positive and negative sides. On the one hand, the possibility of using numeric values ​​of the constants that make up an enumeration type, especially if abused, defeats the purpose of using these types and creates the risk of errors (when numeric values ​​are used for which there are no corresponding constants in the type). On the other hand, explicit value management gives some additional features. For example, it allows you to use enumeration types when organizing an interface with modules written in other languages, if they use or return integer-encoded values ​​from some predefined set.

Another opportunity that enumerated types provide at the language implementation level is memory savings. With a small enumeration type, a few bits are enough to store the value of that type (the Cardsuit type above requires only two bits per value, while a standard integer on most architectures in use takes 32 bits - 16 times more), and the compiler can use this fact serves to compress data storage in memory. This can be especially important if multiple enum type values ​​are stored in a single record - compaction records when processing large quantities of them, it can free up a lot of memory. However, it should be noted that compilers usually do not implement this feature, at least recently, when computer memory has become significantly cheaper.

Criticism

The enumeration type is traditional for developed programming languages, is used quite widely and is often taken for granted. However, this type is also not without criticism from programming theorists and practitioners. So, when developing a programming language Oberon enumerated types were included in the list of features that were removed from the language. Niklaus Wirth, the developer of the language, gave the following reasons:

On the other hand, for example, in Java, which initially did not contain an enumerated type, this type was subsequently introduced for reasons of not only convenience, but also reliability: the problem of using groups of named constants instead of enumerations is that there is no control on the part of the compiler over both the uniqueness of the values ​​of the constants and the possibility of random assignment variable values, which do not correspond to any of these constants.

Description of enumerations in various languages

Enum cardsuit ( CLUBS , DIAMONDS , HEARTS , SPADES );

Dynamic, weakly typed languages ​​with C-like syntax (for example perl or JavaScript), as a rule, do not have enumerations.

C++

C++ enumerations directly inherit the behavior of C enumerations, except that the enum type in C++ is a real type, and keyword enum is only used when declaring this type. If, when processing a parameter that is an enumeration, any value from the enumeration is not processed (for example, one of the elements of the enumeration was forgotten to be processed in a switch construct), then the compiler may issue a warning about a forgotten value.

enum Cardsuit (Clubs, Diamonds, Spades, Hearts)

Java

The original Java did not have enumerations; instead, it was proposed to use classes with static constants. Starting from version 5 (1.5), enumerations were introduced into the language; they represent a full-fledged class to which you can add an arbitrary number of fields and methods. Enumerations were introduced to provide improved control over type safety.

A construct that specifies alternatives for a simple type looks like this:

<простой тип> ::= <перечисляемый тип>

<предопределенный тип>

<ограниченный тип>

In other words, data of a simple type in Pascal can be described as data of an enumerated type (sometimes called a user's own type), predefined or standard type(this type does not need to be described in the types section) and limited type (type segment). It should be remembered that all these types are scalar, that is, their values ​​are ordered in a certain way.

Enum type

When formulating many algorithms in the form of program text, integers are used in the case when their actual numerical value is unimportant and the number indicates only the choice of a value from a small set possible options. So, for example, the days of the week can be encoded this way: Monday - 1, Tuesday - 2, etc. However, no operations other than equality testing or assignment can be performed on these numbers. Trying to add these numbers will result in nonsense. For further use of such data in a program, it is advisable to define its type as enumerated. This will allow:

make the program text easy to read and relieve the programmer from having to encode the values ​​himself;

connect control over the execution of operations, i.e. When trying to multiply Monday by Tuesday, an error message will appear;

provided that the cardinal number of the type is less than or equal to 256, place this data in one byte, i.e. save memory.

The construction defining the rule for describing an enumerated type has the form:

<перечисляемый тип> ::= (<список значений>)

<список значений> ::= <значение>

<список значений>,<значение>

<значение> ::= <идентификатор>

<целое >

Thus, in accordance with the rule, the description of an enumerated type is reduced to a listing in parentheses and separated by commas of the values ​​belonging to the specified type.

An example of a types section with the following descriptions:

Day = (mo, tu, we, th, fr, sa, su); (card(day)=7)

Notation= (do_, re, mi, fa, sol, la, si); (card(notation)=7)

Then, when describing the variables MyDday and MyNota in the variables section:

MyNota: Notation;

You can, for example, use the following assignment operators:

Because a predefined type is scalar, it is useful to define functions for it that return the preceding and subsequent values ​​for their argument. In Pascal, these functions are Pred(x) and Succ(x), respectively. So, as a result of executing the operator MyDay:=Pred(sa), the variable MyDay will be assigned the value fr, and executing the operator MyNota:=Succ(do_) will assign the variable MyNota the value re. It is obvious that these functions are not defined on the “first” and “last” values, respectively, i.e. calls of the form Pred(do_) or Succ(si) will generate an error message. In addition, a significant drawback of the enumerated type is the lack of support for printing its values ​​in the vast majority of cases. existing systems programming, which forces us to use for output, for example, such a fragment of program text.