Mike Torrettinni 198 Posted October 14, 2020 6 hours ago, Lars Fosdal said: Well, we have thousands of meaningful and reasonably obvious names (within their context) - but yeah - remembering them gets harder every year. Age takes its toll. 😛 But - Code Insight should work whether you are assigning or passing as a parameter. Unfortunately, it has often put the enumerated values a long way down the list of candidates. We've only started using 10.4.1, so the jury is still out on this issue, but the LSP has been less than rock solid so far. Most common mistake I make is when enums start with same prefix, like: TCellType = (ctNA, ct...) TCommandType = (ctNA, ct..) If they are within visible area of each other in the unit, you can choose different wording, but very easy to forget that ct is already 'used', if they are defined some time apart. I hope 10.5 will have much much improved LSP. But I must say I kind of like the idea of grouping enums together by content/purpose, within Enums class. Cool solution 🙂 Share this post Link to post
Vandrovnik 214 Posted October 14, 2020 What about scoped enums? http://docwiki.embarcadero.com/RADStudio/Sydney/en/Scoped_Enums_(Delphi) Share this post Link to post
Mike Torrettinni 198 Posted October 14, 2020 Just now, Vandrovnik said: What about scoped enums? http://docwiki.embarcadero.com/RADStudio/Sydney/en/Scoped_Enums_(Delphi) Thanks, this was already suggested. The organized Enums class solution seems very useful: Share this post Link to post
David Heffernan 2345 Posted October 14, 2020 39 minutes ago, Mike Torrettinni said: Most common mistake I make is when enums start with same prefix, like: TCellType = (ctNA, ct...) TCommandType = (ctNA, ct..) If they are within visible area of each other in the unit, you can choose different wording, but very easy to forget that ct is already 'used', if they are defined some time apart. I hope 10.5 will have much much improved LSP. But I must say I kind of like the idea of grouping enums together by content/purpose, within Enums class. Cool solution 🙂 This is exactly the issue that scoped enums solves already. Share this post Link to post
Kryvich 165 Posted October 14, 2020 @Mike Torrettinni I would use different prefixes if possible. Share this post Link to post
Mike Torrettinni 198 Posted October 14, 2020 3 minutes ago, Kryvich said: @Mike Torrettinni I would use different prefixes if possible. I do, except when they are in different units or out of view in longer unit, i can make mistake. Of course it makes sense this is not really applicable for projects where only a few enums are defined and you can remember most of them. But i have a lot of them, so the need to organize them could differ in such cases. Not all projects are the same. Share this post Link to post
David Heffernan 2345 Posted October 14, 2020 19 minutes ago, Kryvich said: I would use different prefixes if possible. That's what scoped enums are meant for Share this post Link to post
Kryvich 165 Posted October 14, 2020 I know, now it is not fashionable to use prefixes, and they prefer to write TCommandType.NA, or even CommandType.NA like in C#. Share this post Link to post
Lars Fosdal 1792 Posted October 14, 2020 Dropping the T for types in Delphi doesn't quite work for scoped types. program ScopedEnumsWithoutT; {$APPTYPE CONSOLE} {$R *.res} {$ScopedEnums ON} uses System.SysUtils; type CommandType = (NA, Whatever); type TClass = class private FCommandType: CommandType; public constructor Create; property CommandType: CommandType read FCommandType write FCommandType; end; procedure Test; begin var Instance := TClass.Create; try Instance.CommandType := CommandType.Whatever; // This is fine finally Instance.Free; end; end; { TClass } constructor TClass.Create; begin CommandType := ScopedEnumsWithoutT.CommandType.NA; // When using "unit name space" - this is fine CommandType := CommandType.NA; // [dcc32 Error] : E2018 Record, object or class type required end; begin try Test; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. Share this post Link to post
Rollo62 536 Posted October 14, 2020 Is NA some kind of reserved word or math function, have you tried with .Whatever too ? Share this post Link to post
Lars Fosdal 1792 Posted October 14, 2020 2 minutes ago, Rollo62 said: Is NA some kind of reserved word or math function, have you tried with .Whatever too ? Changing NA to Nada gives same result. But - adding the "unit scope" works. CommandType := ScopedEnumsWithoutT.CommandType.NA; 1 Share this post Link to post
Vandrovnik 214 Posted October 14, 2020 28 minutes ago, Rollo62 said: Is NA some kind of reserved word or math function, have you tried with .Whatever too ? No; problem is, that in the example above there is type "CommandType" and property "CommandType", so CommandType.NA is trying to reference property CommandType, which does not have member called NA. Share this post Link to post
Marat1961 17 Posted October 14, 2020 (edited) The enumerated type has been removed in oberon. When Niklaus Emil Wirth came to us in Tomsk. We asked him a question, the reason for this was done? We got an answer about his shortcomings. 1. Very often, an enumerated type cannot be extended, This may be due to the fact that it is from a third party library and the domain of its values is already sealed. 2. A set of constants can successfully perform the same role. 3. One and the same concept is often used in different classifications, which leads to the growth of similar names with distinguishing prefixes. 4. The prefix is essentially the same vicious Hungarian notation LPStrZ_to_hell For convenient use, a related set of constants can be placed in a module or record. The record will act as a namespace. Here we will not be limited to expanding the list of values. Also, we can always add related methods for working with these values. THTMLType = record public const Template = 0; Static = 1; Header = 2; Custom = 3; end; Criticism The enumeration type is traditional in advanced programming languages, is widely used and is often taken for granted. However, this type is also not without criticism from programming theorists and practitioners. So, when developing the Oberon programming language, enumerated types were included in the list of features that were removed from the language. Niklaus Wirth, the language developer, gave the following reasons: “In an increasing number of programs, the ill-considered use of enumerations ... leads to a population explosion among types, which, in turn, leads not to clarity of programs, but to verbosity” [1]; when an enumeration type is exported by a module (that is, it becomes part of the interface), the general rule is violated - the type export command simultaneously exports all its elements, while for all other types, the type export hides its internal structure; from the point of view of ensuring readability of programs, nothing prevents you from using just a group of jointly defined named constants instead of an enumerated type, especially when there are language mechanisms such as modules or classes. 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 named constant groups instead of enumerations is that there is no compiler control as to the uniqueness of values constants, and the possibility of random assignment to variables of values that do not correspond to any of these constants. Edited October 14, 2020 by Marat1961 2 Share this post Link to post
Mike Torrettinni 198 Posted October 14, 2020 12 minutes ago, Marat1961 said: THTMLType = record public const Template = 0; Static = 1; Header = 2; Custom = 3; end; Interesting. Are you really using this construct instead of enums, in your real code? Share this post Link to post
Marat1961 17 Posted October 14, 2020 (edited) 52 minutes ago, Mike Torrettinni said: Interesting. Are you really using this construct instead of enums, in your real code? Of course I do. All programmers, for example, in java-script are forced to use the same approach. The original K&R C dialect did not have enumeration types, however they were added in the ANSI C standard. Edited October 14, 2020 by Marat1961 Share this post Link to post
Marat1961 17 Posted October 14, 2020 For example, we took the direction of the cardinal points North South West East. Then he finds out that this is not enough, we decided to add. The question is where to add? Now what to do with that code that uses only 4 directions? Share this post Link to post
Mike Torrettinni 198 Posted October 14, 2020 Just now, Marat1961 said: Of course I do. All programmers, for example, in C ++, are forced to use the same approach. Aha, cool. I know I can use consts in records, but never thought of this approach to replace enums. I guess this whole topic would be pointless if code completion would work as it should. But I like the different approaches and suggestion, and a little history (I assume the discussion with Niklaus wasn't last week 🙂 ). Share this post Link to post
Stefan Glienke 2002 Posted October 14, 2020 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 Share this post Link to post
Guest Posted October 14, 2020 1 minute ago, Mike Torrettinni said: Aha, cool. I know I can use consts in records, but never thought of this approach to replace enums. Not exactly as only enums replacement, i use it for consts, in that way i have my constants tucked, sorted and scoped, no more global consts all over the place, popping in code complete. Share this post Link to post
Marat1961 17 Posted October 14, 2020 (edited) 52 minutes 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.... type TMyType = record const &Template = 0; &Static = 1; Header = 2; Custom = 3; type TMySetType = set of &Template..Custom; end; Edited October 14, 2020 by Marat1961 Share this post Link to post
David Heffernan 2345 Posted October 14, 2020 32 minutes ago, Marat1961 said: All programmers, for example, in C ++, are forced to use the same approach. Don't think so https://en.cppreference.com/w/cpp/language/enum Share this post Link to post
Stefan Glienke 2002 Posted October 14, 2020 20 minutes ago, Marat1961 said: THTMLType = record public const Template = 0; Static = 1; Header = 2; Custom = 3; end; MySet = set of (THTMLType.Template .. THTMLType.Custom); If that would compile - and even if it would that would not prevent that set to be assigned [4] to. Share this post Link to post
Marat1961 17 Posted October 14, 2020 34 minutes ago, David Heffernan said: Don't think so https://en.cppreference.com/w/cpp/language/enum As for C ++, I was in a hurry. Although when porting, I very often port as a list of constants. Wonderful sources for oberon do without enumerated types. In Java, an enumerated type can be inherited and extended. Share this post Link to post
Marat1961 17 Posted October 14, 2020 24 minutes ago, Stefan Glienke said: If that would compile - and even if it would that would not prevent that set to be assigned [4] to. I corrected the syntax of the example Share this post Link to post