Kryvich 165 Posted October 14, 2020 (edited) 1. You cannot extend a set of constants if they are defined in a record type in a third party library. There is no record inheritance. 2. An enumeration give us more type safety than a set of integer constants. 3. Scoped enumerations. 4. I like prefixes. But if not, see 3. I use enums with 100 or more members. If instead of them I used named integer constants, adding and subtracting them, there would be many hard-to-find errors. Edited October 14, 2020 by Kryvich 1 Share this post Link to post
Kryvich 165 Posted October 14, 2020 When I need to add a new member to the enum, I ... just insert the new member into the enum. If I had a set of named constants, I would have to renumber all the constants starting from the insertion position. So what about extensibility? 1 Share this post Link to post
Marat1961 17 Posted October 14, 2020 (edited) 21 minutes ago, Kryvich said: 1. You cannot extend a set of constants if they are defined in a record type in a third party library. There is no record inheritance. 2. An enumeration give us more type safety than a set of integer constants. 3. Scoped enumerations. 4. I like prefixes. But if not, see 3. I use enums with 100 or more members. If instead of them I used named integer constants, adding and subtracting them, there would be many hard-to-find errors. Why do you need to inherit records? If I know the value of the constant, I don't need anything else. Also, no one forbids transferring the api header files. Take tlb for example, constants are beautifully declared in it. Within the module. Can be within a record or class. When I use Windows dll I can perfectly use the constants from the header file. Edited October 14, 2020 by Marat1961 Share this post Link to post
Marat1961 17 Posted October 14, 2020 13 minutes ago, Kryvich said: When I need to add a new member to the enum, I ... just insert the new member into the enum. If I had a set of named constants, I would have to renumber all the constants starting from the insertion position. So what about extensibility? Or you can add a new value to the end of the list. For example, we take Google protocol buffer, where tags are used to identify fields. Do not touch the old field identifiers unless you want to break anything. Share this post Link to post
Marat1961 17 Posted October 14, 2020 27 minutes ago, Kryvich said: Scoped enumerations. If you put in a record or a class, the type name will be a namespace. To refer to a constant you use the dot notation Record_type.Constant_name Share this post Link to post
Marat1961 17 Posted October 14, 2020 55 minutes ago, Kryvich said: I use enums with 100 or more members. If instead of them I used named integer constants, adding and subtracting them, there would be many hard-to-find errors. I remember where I had to use an enumerated type of this size. Probably the largest type is tokens in the parser. But now I use the compiler of the compiler. In my opinion, when there are a lot of objects, they no longer work by name. The head and brains do not need to be overloaded. For identification, you already need to use handlers. So that there is no desire to cope with them, you can put the whole in the record. hParam = record v: Cardinal; end; hParamHelper = record Helper for hParam constructor From (v: Cardinal); function request: hRequest; inline; end; or they write well herehttp://gamesfromwithin.com/managing-data-relationships Share this post Link to post
Kryvich 165 Posted October 14, 2020 Members of an enum are not objects. For ex. I have IDs of syntax relations of words in a natural language (about 200 IDs). The numerical values of the enumeration members are not important to us, only their names matter. Therefore, there is no need to specify integer values for each member of an enum in your program. 1., 2., 3., 4. - it was the answer to the words of Wirth, which you quoted earlier. Quote If I know the value of the constant, I don't need anything else. Enumerations were invented in order not to use ordinalities of its members directly. And so as not to (accidentally) add, subtract and divide them like numbers. This is Pascal where type safety matters. Quote Also, no one forbids transferring the api header files. Take tlb for example, constants are beautifully declared in it. Headers can use enums as well. It depends on how the С-language headers are translated into Pascal code. Quote Do not touch the old field identifiers unless you want to break anything. With enumerations, you can reorder old values as you want. And nothing will break if the ordinalities are not directly used anywhere. Quote If you put in a record or a class, the type name will be a namespace. Overcomplication, misuse of software entities. 2 Share this post Link to post
Rollo62 536 Posted October 15, 2020 Interesting philosophical discussion. I like and use enums heavily, always with full scope and "T"-named for safety reasons (to avoid cases as in the start of this thread). Of course I know some people like the "non-prefixed" version of everything, this I think leads to many issues. On the other hand, the record proposal from @Marat1961 is worth considering too, as a good 2nd alternative. Maybe they can nicely coexist both, with their pros and cons, I won't fell disturbed too much. I see also one very practical benefit that speaks for enums nowadays: They can use class helpers. From that I make also heavy use, leading to focus code where it belongs to. I'm not 100% sure, since I never checked that, but I think class helpers won't work on consts. Share this post Link to post
Fr0sT.Brutal 900 Posted October 15, 2020 15 hours ago, Stefan Glienke said: And I thought enums and the possibility to build sets of enums is one of those unique features in Delphi that many other languages such as C++ don't have hence you have to and/or with damn bitmasks.... +1. The most useful and powerful Delphi feature which I miss in other languages. These bunches of constants are just ugly and - what's more important - they do not allow type checking. 1 Share this post Link to post
Vandrovnik 214 Posted October 15, 2020 3 minutes ago, Fr0sT.Brutal said: +1. The most useful and powerful Delphi feature which I miss in other languages. These bunches of constants are just ugly and - what's more important - they do not allow type checking. Exactly - my most stupid and most difficult to find mistakes in OpenGL came from using wrong constant (with similar name to the correct one). Share this post Link to post
Lars Fosdal 1792 Posted October 15, 2020 A pitfall with Enums is that they are so easy to change. Add another member in the middle of the list, and you have changed the ordinal value of the rest. This is fine if you only use the enumerated reference inside your application, but if you use the ordinal - f.x. when saving to/retrieving from a database, or when transmitting to another system - you get into trouble. Share this post Link to post
Rollo62 536 Posted October 15, 2020 (edited) Yes, but that may happen too when you insert a new value in a consts list, and re-order their values to make it ordered more nicely. Exactly such cases I handle in the enum itself by class helpers ToXxx and FromXxx. Working with number ranges inside an enum, I can even implement a "poor man's grouping", like enum 0 ... 99 ==> Isgroup1 enum 100 ... 199 ==> Isgroup2 All this well supported by class helpers, with least memory footprint. Edited October 15, 2020 by Rollo62 Share this post Link to post
Vandrovnik 214 Posted October 15, 2020 (edited) 24 minutes ago, Lars Fosdal said: A pitfall with Enums is that they are so easy to change. Add another member in the middle of the list, and you have changed the ordinal value of the rest. This is fine if you only use the enumerated reference inside your application, but if you use the ordinal - f.x. when saving to/retrieving from a database, or when transmitting to another system - you get into trouble. You can use: type tTestEnum = (None=0, One=1, Eight=8); Edited October 15, 2020 by Vandrovnik Share this post Link to post
Lars Fosdal 1792 Posted October 15, 2020 8 minutes ago, Vandrovnik said: You can use: type tTestEnum = (None=0, One=1, Eight=8); Which causes problems for RTTI. Share this post Link to post
Fr0sT.Brutal 900 Posted October 15, 2020 1 hour ago, Lars Fosdal said: if you use the ordinal - f.x. when saving to/retrieving from a database, or when transmitting to another system - you get into trouble. If you use ordinal values of an enum you already are likely to get into trouble, not talking about data exchange with other systems. Share this post Link to post
Lars Fosdal 1792 Posted October 15, 2020 Well, it is all about littering the code with comments like "do not remove or reorder elements" 😛 Share this post Link to post
Fr0sT.Brutal 900 Posted October 15, 2020 1 hour ago, Lars Fosdal said: Well, it is all about littering the code with comments like "do not remove or reorder elements" Hmm, I think of enums like of an abstraction. I don't care what number has "enumFoo", I often won't notice if it had no number at all. All I want is that "enumFoo" is member of type "TEnumFoo" and (sometimes) that it goes after "enumLaz" and before "enumBar". If I need to let it go beyond my application, I'll use its string name "enumFoo" or special string from "FooNames: array[TEnumFoo] of string". Number values are applied only when I'm sure the definition of enum is consistent (f.ex., between two apps of the same complex). 2 Share this post Link to post
Lars Fosdal 1792 Posted October 15, 2020 You store Enums as strings in the database? Share this post Link to post
Kryvich 165 Posted October 15, 2020 3 hours ago, Lars Fosdal said: This is fine if you only use the enumerated reference inside your application, but if you use the ordinal - f.x. when saving to/retrieving from a database, or when transmitting to another system - you get into trouble. It is why textual exchange and API formats were invented. XML, JSON, YAML. It's why Microsoft replaced the binary format DOC with DOCX. Do not pass an enumeration member by its numeric value, use its name. 1 Share this post Link to post
Kryvich 165 Posted October 15, 2020 As for its own database, the program may store the enumerations in a field of any type: text, binary. But if a programmer chooses the binary format, then it is his responsibility to correctly interpret the stored data. It is possible, for example, to add a format version to the database and interpret the stored data accordingly. Share this post Link to post
Rollo62 536 Posted October 15, 2020 (edited) 41 minutes ago, Kryvich said: Do not pass an enumeration member by its numeric value, use its name. Yes, but also names might change over time, so thats no real benefit over numbers. All right, numbers have a higher risk of being re-ordered, but in principle: "enums might change over time". Thats on reason why I prefer the conversion logic nearby, in enum's class helper itself. There I have only one point of logic, where I could even do some conversion corrections from different enum-type versions. Edited October 15, 2020 by Rollo62 Share this post Link to post
Marat1961 17 Posted October 15, 2020 17 hours ago, Kryvich said: 17 hours ago, Kryvich said: Overcomplication, misuse of software entities. That is, you so interpret the declaration of constants inside the record? Share this post Link to post
Kryvich 165 Posted October 15, 2020 Don't take it to heart. Sometimes it is difficult to find the right English words, which makes my sentences sound too categorical. Share this post Link to post
Marat1961 17 Posted October 15, 2020 18 hours ago, Kryvich said: Members of an enum are not objects. For ex. I have IDs of syntax relations of words in a natural language (about 200 IDs). The numerical values of the enumeration members are not important to us, only their names matter. Therefore, there is no need to specify integer values for each member of an enum in your program. I am not forcing you to use this programming style. In my programs at the domain level, I also make extensive use of enumerated types. I consider it permissible to use them even in the library if it is available in the source. But knowing the pitfalls of using them is probably not bad. Niklaus Wirth for me is a GURU of the highest level I would have already thought about their organization and semantic separation. It is possible that these names should be organized into some taxnomy, and maybe even more than one. And what kind of subject area, knowledge base? May I have a look at the code of your project? Type declarations and how you use them. Share this post Link to post