### Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

### Author Topic: Proposing 4 New Ideas - #1 Enumerations  (Read 1913 times)

#### IndigoBoy83

• New member
• Posts: 9
##### Proposing 4 New Ideas - #1 Enumerations
« on: March 22, 2019, 01:23:30 pm »
PAGE #1A - Introducing Enumerations, and Evalues on Enumerations

We create a new type: enumerations (Shortened to "enums").
We create a new type of variable: evalues (Shortened to "evals").

An enumeration is a list of evalues.

An evalue is defined "on" some enumeration.

We suggest here that the evalue "void" should AUTOMATICALLY be included into every enumeration by force so all programmers can share it.
Also, the following enumerations are all equivalent: "void", "void.void", "void.void.void", etc.

The "root" of an evalue is the name of the enumeration of which is prescribes to.

We suggest that the enumeration of all types defined in a program be called "etypes".

We have an "eval on everything" if no enumeration is given.  By default, this enumeration is of etypes, which is any evalues present in any enumerations.

Consider the code:

Code: Pascal  [Select][+][-]
1. type
2.     enum1 : enum = ( big, bad, ugly );
3.     enum2 : enum = ( big, good, smart );
4.     enum3 : enum = ( smart, bright );
5. var
6.    eval1 : eval on enum1;
7.    eval2 : eval on enum2;

If a particular evalue "eval1" is set to another evalue "eval2", then we'd write the code:

Code: Pascal  [Select][+][-]
1. eval1 := eval2;

Notice, this will be executed (in runtime) *only* if the actual value of eval2 resides in the enumeration enum1 of eval1.  If it does NOT reside in that said enumeration then the line of code will be IGNORED.  So:

Code: Pascal  [Select][+][-]
1. eval1 := enum1.big;  // Works!
2. eval1 := enum2.smart;  // IGNORED!

Notice, an evalue can be given which has no root and still work:

Code: Pascal  [Select][+][-]
1. eval1 := big;  // Works!
2. eval1 := smart;  // IGNORED!

We introduce the function "str" which returns a string representation of an evalue.  Observe:

Code: Pascal  [Select][+][-]
2. writeln( 'eval1 = ', str(eval1) );  // writes the value of eval1

We can make a listing of all evals in an enumerations by the following: One can delineate the evalues of an enumeration by using the square brackets "[" and "]".  This is demonstrated below:

Code: Pascal  [Select][+][-]
1. writeln( '1st evalue in enum1: ', str(enum1[1]) );
2. writeln( '2nd evalue in enum1: ', str(enum1[2]) );
3. writeln( '3rd evalue in enum1: ', str(enum1[3]) );
4. writeln( '4th evalue in enum1: ', str(enum1[4]) );
5. writeln( '5th evalue in enum1: ', str(enum1[5]) );

Note, when accessing an evalue that is not present in an enumeration then we get the standard evalue "void".

1st evalue in enum1: big
3rd evalue in enum1: ugly
4th evalue in enum1: void
5th evalue in enum1: void

We introduce the compiler words "exists in" so that one can test whether some evalue resides in some enumeration:

Code: Pascal  [Select][+][-]
1. if eval1 exists in enum2 then writeln('The evalue ', str(eval1), ' exists in the enumeration enum2');

It should be allowed to create new enumerations recycling old ones by using unions, intersections, and negations of them.

We write "union enumeration" as "OR".
We write "intersection enumeration" as "AND".
We write "negation enumeration" as "NOT".

For example, using the above enum1, enum2 and enum3, we create:

Code: Pascal  [Select][+][-]
1. type
2.     enum4 : enum = enum1 OR enum2;
3.     enum5 : enum = enum1 AND enum2;
4.     enum6 : enum = (enum1 OR enum2) AND (NOT enum3).

enum4 now consists of the five evalues: big, bad, ugly, good, smart
enum5 now consists of the one evalue: big
enum6 now consists of the four evalues: big, bad, ugly, good

Notice that every enumeration *must* be properly defined in the "type section" of the program.  That is, every enumeration must have a *proper* name for otherwise the compiler will be confused as to what the root of the enumeration is for a given evalue.

One can create an enumeration *on* an enumeration as follows:

Code: Pascal  [Select][+][-]
1. type
2.     enum7 : enum = (enum1, enum2);

enum7 now consists of the five evalues: enum1.big, enum1.bad, enum1.ugly, enum2.big, enum2.good, enum2.smart

This allows enumerations to be nested within others.

The following is sample code:

Code: Pascal  [Select][+][-]
1. Program Example_Using_Evalues_On_Enumerations;
2.
3. type
4.     colors : enum = ( blue, red, black );
5.     sizes : enum = ( small, medium, big );
6.     brands : enum = ( honda, ford );
7.     faces : enum = ( colors, sizes );
8.
9. var
10.    myeyecolor : eval on colors;
11.    mynosesize : eval on sizes;
12.    mycarbrand : eval on brands;
13.    myface : eval on faces;  // NOTE: Only color (in my eye) and size (in my nose) can reside in faces.  The evalue of brand (in my car) cannot.
14.
15.    some_eval : eval;  // The "default" eval is on "etypes"
16.
17. begin
18.   // Setting myeyecolor to black, mynosesize to medium, mycarbrand to honda
19.
20.     writeln( 'Setting myeyecolor to black, mynosesize to medium, and mycarbrand to honda' );
21.
22.     myeyecolor := colors.black;
23.     mynosesize := sizes.medium;
24.     mycarbrand := brand.honda;
25.
26.     writeln( '(1) My eyecolor: ', str(myeyecolor) );  // Will output "(1) My eyecolor: colors.black"
27.     writeln( '(1) My nosesize: ', str(mynosesize) );  // Will output "(1) My nosesize: sizes.medium"
28.     writeln( '(1) My carbrand: ', str(mycarbrand) );  // Will output "(1) My carbrand: brands.honda"
29.
30.   // Something about myface is either black (in myeyecolor) or medium (in mynosesize) but NOT honda (mycarbrand)
31.
32.     writeln( 'Something about myface is either colors.black or sizes.medium but NOT brand.honda' );
33.
34.     myface := myeyecolor;
35.     writeln( '(2) Something about my face: ', str(myface) );  // Will output "(2) Something about my face: colors.black"
36.
37.     myface := mynosesize;
38.     writeln( '(2) Something about my face: ', str(myface) );  // Will output "(2) Something about my face: sizes.medium"
39.
40.     myface := mycarbrand;  // This line is IGNORED because mycarbrand isn't something in things_aboutmyface
41.     writeln( '(2) Something about my face: ', str(myface) );  // Will again output "(2) Something about my face: sizes.medium" (which was set before)
42.
43.   // Listing all the evalues in enumeration things_aboutmyface
44.
45.     writeln( 'Listing evalues in faces' );
46.
47.     writeln( '(3) faces[1]: ', str(faces[1]) );  // Will output "(3) faces[1]: colors.blue"
48.     writeln( '(3) faces[2]: ', str(faces[2]) );  // Will output "(3) faces[2]: colors.red"
49.     writeln( '(3) faces[3]: ', str(faces[3]) );  // Will output "(3) faces[3]: colors.black"
50.     writeln( '(3) faces[4]: ', str(faces[4]) );  // Will output "(3) faces[4]: sizes.small"
51.     writeln( '(3) faces[5]: ', str(faces[5]) );  // Will output "(3) faces[5]: sizes.medium"
52.     writeln( '(3) faces[6]: ', str(faces[6]) );  // Will output "(3) faces[6]: sizes.big"
53.     writeln( '(3) faces[7]: ', str(faces[7]) );  // Will output "(3) faces[7]: void"
54.     writeln( '(3) faces[8]: ', str(faces[8]) );  // Will output "(3) faces[8]: void"
55.
56.   // Resetting myeyecolor as blue using some_eval
57.
58.      some_eval := blue;
59.      writeln( 'Some_eval: ', str(some_eval) );  // Will output "Some_eval: blue".  NOTE: this eval does not have a root.
60.      writeln( 'Setting myeyecolor, mynosesize, and mycarbrand to some_eval (some will be ignored)' );
61.
62.      myeyecolor := some_eval;
63.      mynosesize := some_eval;  // This line is IGNORED because the evalue of some_eval right now (blue) is not in sizes
64.      mycarbrand := some_eval;  // This line is IGNORED because the evalue of some_eval right now (blue) is not in brands
65.
66.      writeln( '(4) My eyecolor: ', str(myeyecolor) );  // Will output "(4) My eyecolor: colors.blue"
67.      writeln( '(4) My nosesize: ', str(mynosesize) );  // Will output "(4) My nosesize: sizes.medium"
68.      writeln( '(4) My carbrand: ', str(mycarbrand) );  // Will output "(4) My carbrand: brands.honda"
69.
70.   // Setting everything to void
71.
72.      some_eval := void;
73.      writeln( 'Some_eval: ', str(some_eval) );  // Will output "Some_eval: void"
74.      writeln( 'Setting myeyecolor, mynosesize, and mycarbrand to some_eval (none will be ignored)' );
75.
76.      myeyecolor := some_eval;
77.      mynosesize := some_eval;
78.      mycarbrand := some_eval;
79.
80.      writeln( '(5) My eyecolor: ', str(myeyecolor) );  // Will output "(5) My eyecolor: colors.void"
81.      writeln( '(5) My nosesize: ', str(mynosesize) );  // Will output "(5) My nosesize: sizes.void;"
82.      writeln( '(5) My carbrand: ', str(mycarbrand) );  // Will output "(5) My nosesize: cars.void;"
83. end.

The output of the above code:

Code: Pascal  [Select][+][-]
1. Setting myeyecolor to black, mynosesize to medium, and mycarbrand to honda
2. (1) My eyecolor: colors.black
3. (1) My nosesize: sizes.medium
4. (1) My carbrand: brands.honda
5. Something about myface is either colors.black or sizes.medium but NOT brand.honda
6. (2) Something about my face: colors.black
7. (2) Something about my face: sizes.medium
8. (2) Something about my face: sizes.medium
9. Listing evalues in faces
10. (3) faces[1]: colors.blue"
11. (3) faces[2]: colors.red"
12. (3) faces[3]: colors.black"
13. (3) faces[4]: sizes.small"
14. (3) faces[5]: sizes.medium"
15. (3) faces[6]: sizes.big"
16. (3) faces[7]: void"
17. (3) faces[8]: void"
18. Some_eval: blue
19. Setting myeyecolor, mynosesize, and mycarbrand to some_eval (some will be ignored)
20. (4) My eyecolor: colors.blue
21. (4) My nosesize: sizes.medium
22. (4) My carbrand: brands.honda
23. Some_eval: void
24. Setting myeyecolor, mynosesize, and mycarbrand to some_eval (none will be ignored)
25. (5) My eyecolor: colors.void
26. (5) My nosesize: sizes.void
27. (5) My nosesize: cars.void

------------------------------------------------------------------
PAGE #1B - Introducing Esets on Enumerations

We now create sets of evalues which we call "esets".

An eset is defined "of" some enumeration.

Every enumeration can be used to define an eset; that is, any enumeration in the definition of an eset represents an eset of the enumeration where all of its evalues are present.

The following code describes its use:

Code: Pascal  [Select][+][-]
1. Program Example_Using_Esets_Of_Enumerations;
2.
3. type
4.     colors : enum = ( blue, red, black, green );
5.
6. Procedure Describe_Painting( apainting : eset of colors );
7. var
8.    acolor : eval on colors;
9. begin
10.   for acolor in apainting do
11.     writeln( 'The color ', str(acolor), ' is in the painting.' );
12. end;
13.
14. var
15.    mypainting : eset of colors;
16.
17. begin
18.   writeln('Making mypainting "blue AND red"');
19.   mypainting := blue AND red;
20.   Describe_Painting( mypainting );  // Will output that the colors blue and red are in mypainting
21.
22.   writeln('Making mypainting "(colors) AND NOT (blue OR red)"');
23.   mypainting := (colors) AND NOT (blue OR red);
24.   Describe_Painting( mypainting );  // Will output that the colors black and green are in mypainting
25. end.

The output of the above code:

Making mypainting "blue AND red"
The color blue is in the painting.
The color red is in the painting.
Making mypainting "(colors) AND NOT (blue OR red)"
The color black is in the painting.
The color green is in the painting.

We introduce the function "ord" which returns a numeral to the placing of an evalue in a given enumeration.

A variable whose type is an eset is constructed in the RAM as a sequence of bits, the number of which is equivalent to the number of evalues in the enumeration to which it perscribes to.  If the ith evalue in the enumeration is present in the eset, then the ith bit in the variable is 1.  Conversely, if the ith evalue in the enumeration is not present in the eset, then the ith bit in the variable is 0.  So, we introduce the ability to use the weird-brackets "{" and "}" to indicate which bit of a variable should be accessed/altered.  (I strongly believe the use of the weird-brackets should be henceforth used in general to delineate the bit of ANY VARIABLE.  The use of these brackets as comments should be changed/abandoned.)

As example:

Code: Pascal  [Select][+][-]
1. Program Further_Examples_Using_Evalues_And_Esets;
2.
3. type
4.     colors : enum = ( blue, red, black, green, orange, purple, yellow );
5.
6. Procedure Write_Colors( _setcolors : eset of color );
7. var
8.    acolor : eval on colors;
9. begin
10.   for acolor in colors do
11.     write( ord(acolor), str(acolor), ' ' );
12.   writeln;
13. end;
14.
15. var
16.    myclothingcolors : eset of colors;
17.
18. begin
19.   writeln( 'The following colors exist:' );
20.   Write_Colors( colors );
21.
22.   myclothingcolors := blue AND black AND purple;
23.
24.   writeln( 'My clothing is colored: ' );
25.   Write_Colors( myclothingcolors );
26.
27.   writeln( 'Changing my attire (clothes)' );
28.
29.   myclothingcolors{1} := 0;  // not present
30.   myclothingcolors{2} := 1;  // present
31.   myclothingcolors{3} := false;  // not present
32.   myclothingcolors{4} := true;  // present
33.   myclothingcolors{5} := 5-5;  // not present
34.   myclothingcolors{6} := 6-5;  // present
35.   myclothingcolors{7} := true AND false;  // not present
36.
37.   writeln( 'My clothing is now colored: ' );
38.   Write_Colors( myclothingcolors );
39. end.

The output of the above code:

The following colors exist:
1blue 2red 3black 4green 5orange 6purple 7yellow
My clothing is colored:
1blue 3black 6purple
Changing my attire (clothes)
My clothing is now colored:
2red 4green 6purple

Notice that although the evalue "void" is present in every enumeration, when one makes the call such as "for acolor in colors do.." we will never get acolor taking on the value of "void"; it is simply not allowed by force.
« Last Edit: March 22, 2019, 02:19:01 pm by IndigoBoy83 »

#### marcov

• Global Moderator
• Hero Member
• Posts: 8715
• FPC developer.
##### Re: Proposing 4 New Ideas - #1 Enumerations
« Reply #1 on: March 22, 2019, 02:06:07 pm »
- "void" is not a Pascal standard. Empty set would be logical, but these are enums, not sets.
- seems rather stringly typed.
- What should happen if I assign enum2.big to eval1 ?

Besides I fail to see any practical benefit to this feature, or why you would need to mix identifiers from various enum types.

#### Ñuño_Martínez

• Hero Member
• Posts: 1051
##### Re: Proposing 4 New Ideas - #1 Enumerations
« Reply #2 on: March 24, 2019, 12:57:16 pm »
Did a diagonal reading* and I think this is just add complexity to actual Pascal enumerations without any real advantage.  Also I don't get the use of the of and on keywords.  May be you're confused and you think you're talking about a different programing language (ADA? Algol? ...).
_________________

* Just read spare phrases and sections instead of read all the text.  Mostly small paragraphs and code snippets.
« Last Edit: March 24, 2019, 12:59:55 pm by Ñuño_Martínez »
Are you interested in game programming? Join the Pascal Game Development community!
Also visit the Game Development Portal

#### ASBzone

• Sr. Member
• Posts: 459
##### Re: Proposing 4 New Ideas - #1 Enumerations
« Reply #3 on: March 24, 2019, 04:17:52 pm »
PAGE #1A - Introducing Enumerations, and Evalues on Enumerations

This is interesting, but the one question that seems to remain unanswered is, what advantage would this feature offer?

I liked the STR function which would make it easier to use and display values in a set, but beyond that, I couldn't see what the advantage of all the rest was.

What problem or problems would be eliminated by the implementation of this functionality?  I cannot speak for others, but I found it hard to understand that part.
-ASB: https://www.BrainWaveCC.com

Lazarus v2.0.11 r63516 / FPC v3.2.1-r46879 (via FpcUpDeluxe) -- Windows 64-bit install w/32-bit cross-compile
Primary System: Windows 10 Pro x64, Version 2004 (Build 19041.388)
Other Systems: Windows 10 Pro x64, Version 2004 or greater

#### BeniBela

• Hero Member
• Posts: 753
##### Re: Proposing 4 New Ideas - #1 Enumerations
« Reply #4 on: March 24, 2019, 04:38:18 pm »
Perhaps it could be useful to extend enumerations?

Like for string list sorting there is an enum TStringsSortStyle = (sslNone,sslUser,sslAuto). Someone who extends string list, might want to add more sorting modes, e.g. sslAutoAscending, sslAutoDescending, sslAutoNumeric, ..., but atm you can't extend the enum

#### lucamar

• Hero Member
• Posts: 3017
##### Re: Proposing 4 New Ideas - #1 Enumerations
« Reply #5 on: March 24, 2019, 06:15:22 pm »
Perhaps it could be useful to extend enumerations?

Like for string list sorting there is an enum TStringsSortStyle = (sslNone,sslUser,sslAuto). Someone who extends string list, might want to add more sorting modes, e.g. sslAutoAscending, sslAutoDescending, sslAutoNumeric, ..., but atm you can't extend the enum

Extending base types must always be done, if at all, with extreme care and having very clear what the objective is and whether there is a real need to extend the type.

In the case you cite, for example, it's not only uneeded but actively harmful. What you want isn't realy an extension of sorting modes but a ... let's call it "specialization" of sslAuto, so it's better to create a new enumeration + set, say:
Code: Pascal  [Select][+][-]
1. TAutoSortStyles = (assDefault, assDescending, assNumeric); {Default is Alpha-Ascending}
2. TAutoSortStyle = set of TAutoSortStyles;

All you would need then is to override the default sort to take into account a new property, say:
AutoSortStyle: TAutoSortStyle;

And all that, without having to touch a hair of the compiler
« Last Edit: March 24, 2019, 06:18:57 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!)
Lazarus 2.0.8/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

#### PascalDragon

• Hero Member
• Posts: 2093
• Compiler Developer
##### Re: Proposing 4 New Ideas - #1 Enumerations
« Reply #6 on: March 25, 2019, 09:20:51 am »
I liked the STR function which would make it easier to use and display values in a set, but beyond that, I couldn't see what the advantage of all the rest was.
In Write(ln) you can already directly use enum values and have their names printed. Same with WriteStr. Using generic functions you can even wrap that into a function instead of having to declare an additional variable. And to display a whole set one can always use TypInfo.SetToString.

• Sr. Member
• Posts: 459