Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2012-12

Extending an enumeration

9 messages · 3 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Mark Morgan Lloyd

Is it possible to extend an enumeration, while preserving strong type checking? In other words, given existing code like

type    TUpstreamServerCapabilitiesBase= (uscConnected, uscCanIssueGUID);
         TLocalServerCapabilitiesBase= (lscConnected, lscCanIssueGUID,
lscIsFirebird);
         TUpstreamServerCapabilities= set of
TUpstreamServerCapabilitiesBase;
         TLocalServerCapabilities= set of TLocalServerCapabilitiesBase;

can the common parts of those enumerations- whether a connection was initially established and so on- be moved into a common declaration, preferably using "classical" Pascal so that I can store capabilities as a set?

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

JC Chu
to Mark Morgan Lloyd

It is not possible to extend an enumeration type. If you are not willing to use separate sets to hold common and extended elements, you can use a generic (not parametric) set type, say SET OF 0..31, that can hold all possible elements, and define the possible elements as constants.

Mark Morgan Lloyd wrote 23 lines
Is it possible to extend an enumeration, while preserving strong type checking? In other words, given existing code like type TUpstreamServerCapabilitiesBase= (uscConnected, uscCanIssueGUID); TLocalServerCapabilitiesBase= (lscConnected, lscCanIssueGUID, lscIsFirebird); TUpstreamServerCapabilities= set of TUpstreamServerCapabilitiesBase; TLocalServerCapabilities= set of TLocalServerCapabilitiesBase; can the common parts of those enumerations- whether a connection was initially established and so on- be moved into a common declaration, preferably using "classical" Pascal so that I can store capabilities as a set? -- Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues] _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Best regards, JC Chu

Reply by email

Ludo Brands
to Mark Morgan Lloyd: Is it possible to extend an enumeration, while preserving strong type checking? In other…
Mark Morgan Lloyd wrote 16 lines
Is it possible to extend an enumeration, while preserving strong type checking? In other words, given existing code like type TUpstreamServerCapabilitiesBase= (uscConnected, uscCanIssueGUID); TLocalServerCapabilitiesBase= (lscConnected, lscCanIssueGUID, lscIsFirebird); TUpstreamServerCapabilities= set of TUpstreamServerCapabilitiesBase; TLocalServerCapabilities= set of TLocalServerCapabilitiesBase; can the common parts of those enumerations- whether a connection was initially established and so on- be moved into a common declaration, preferably using "classical" Pascal so that I can store capabilities as a set?

Not sure I understand what you are trying to do but perhaps you are looking for subrange types:

type
    TAllServerCapabilitiesBase=(uscConnected,
uscCanIssueGUID,lscConnected, lscCanIssueGUID, lscIsFirebird);
    TUpstreamServerCapabilitiesBase= uscConnected .. uscCanIssueGUID;
    TLocalServerCapabilitiesBase= lscConnected..lscIsFirebird;
    TAllServerCapabiliets=set of TAllServerCapabilitiesBase;
    TUpstreamServerCapabilities= set of TUpstreamServerCapabilitiesBase;
    TLocalServerCapabilities= set of TLocalServerCapabilitiesBase;

Ludo

Reply by email

Mark Morgan Lloyd
to JC Chu: It is not possible to extend an enumeration type. If you are not willing to use separate…
JC Chu wrote 5 lines
It is not possible to extend an enumeration type. If you are not willing to use separate sets to hold common and extended elements, you can use a generic (not parametric) set type, say SET OF 0..31, that can hold all possible elements, and define the possible elements as constants.

Yes, except that that loses type checking.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Mark Morgan Lloyd
to Ludo Brands: Not sure I understand what you are trying to do but perhaps you are looking for subrange…
Ludo Brands wrote 29 lines
On 28/12/2012 11:42, Mark Morgan Lloyd wrote: > Is it possible to extend an enumeration, while preserving strong type > checking? In other words, given existing code like > > type TUpstreamServerCapabilitiesBase= (uscConnected, uscCanIssueGUID); > TLocalServerCapabilitiesBase= (lscConnected, lscCanIssueGUID, > lscIsFirebird); > > TUpstreamServerCapabilities= set of > TUpstreamServerCapabilitiesBase; > TLocalServerCapabilities= set of TLocalServerCapabilitiesBase; > > can the common parts of those enumerations- whether a connection was > initially established and so on- be moved into a common declaration, > preferably using "classical" Pascal so that I can store capabilities > as a set? > Not sure I understand what you are trying to do but perhaps you are looking for subrange types: type TAllServerCapabilitiesBase=(uscConnected, uscCanIssueGUID,lscConnected, lscCanIssueGUID, lscIsFirebird); TUpstreamServerCapabilitiesBase= uscConnected .. uscCanIssueGUID; TLocalServerCapabilitiesBase= lscConnected..lscIsFirebird; TAllServerCapabiliets=set of TAllServerCapabilitiesBase; TUpstreamServerCapabilities= set of TUpstreamServerCapabilitiesBase; TLocalServerCapabilities= set of TLocalServerCapabilitiesBase;

Thanks, but I was hoping for something the other way round i.e.:

type	TCommonServerCapabilitiesBase= (scConnected, scCanIssueGUID);
         TLocalServerCapabilitiesBase(TCommonServerCapabilitiesBase) +=
		(lscIsFirebird); // INVALID CODE, EXAMPLE ONLY.
	TLocalServerCapabilities= set of TLocalServerCapabilitiesBase;

I'd be fairly happy with any solution that did the necessary type/range

Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Ludo Brands
to Mark Morgan Lloyd
Mark Morgan Lloyd wrote 23 lines
Ludo Brands wrote: > type > TAllServerCapabilitiesBase=(uscConnected, > uscCanIssueGUID,lscConnected, lscCanIssueGUID, lscIsFirebird); > TUpstreamServerCapabilitiesBase= uscConnected .. uscCanIssueGUID; > TLocalServerCapabilitiesBase= lscConnected..lscIsFirebird; > > TAllServerCapabiliets=set of TAllServerCapabilitiesBase; > TUpstreamServerCapabilities= set of TUpstreamServerCapabilitiesBase; > TLocalServerCapabilities= set of TLocalServerCapabilitiesBase; Thanks, but I was hoping for something the other way round i.e.: type TCommonServerCapabilitiesBase= (scConnected, scCanIssueGUID); TLocalServerCapabilitiesBase(TCommonServerCapabilitiesBase) += (lscIsFirebird); // INVALID CODE, EXAMPLE ONLY. TLocalServerCapabilities= set of TLocalServerCapabilitiesBase; I'd be fairly happy with any solution that did the necessary type/range checking at runtime.

Enumerations have an ordinal value that starts with 0 by default. "Combining" enumerations has to make sure the ordinal values are different. As a result you can go from bigger to smaller but not the other way around. In your case with 2 subranges you could do something like:

type
    TAllServerCapabilitiesBase=(uscWhatever scConnected,
scCanIssueGUID,  lscIsFirebird);
    TUpstreamServerCapabilitiesBase= uscWhatever .. uscCanIssueGUID;
    TLocalServerCapabilitiesBase= scConnected..lscIsFirebird;

Just make sure you put the common values in the middle.

Ludo

Reply by email

Ludo Brands
to Ludo Brands
Ludo Brands wrote 34 lines
On 28/12/2012 12:48, Mark Morgan Lloyd wrote: > Ludo Brands wrote: >> type >> TAllServerCapabilitiesBase=(uscConnected, >> uscCanIssueGUID,lscConnected, lscCanIssueGUID, lscIsFirebird); >> TUpstreamServerCapabilitiesBase= uscConnected .. uscCanIssueGUID; >> TLocalServerCapabilitiesBase= lscConnected..lscIsFirebird; >> >> TAllServerCapabiliets=set of TAllServerCapabilitiesBase; >> TUpstreamServerCapabilities= set of TUpstreamServerCapabilitiesBase; >> TLocalServerCapabilities= set of TLocalServerCapabilitiesBase; > > Thanks, but I was hoping for something the other way round i.e.: > > type TCommonServerCapabilitiesBase= (scConnected, scCanIssueGUID); > > TLocalServerCapabilitiesBase(TCommonServerCapabilitiesBase) += > (lscIsFirebird); // INVALID CODE, EXAMPLE ONLY. > > TLocalServerCapabilities= set of TLocalServerCapabilitiesBase; > > I'd be fairly happy with any solution that did the necessary > type/range checking at runtime. > Enumerations have an ordinal value that starts with 0 by default. "Combining" enumerations has to make sure the ordinal values are different. As a result you can go from bigger to smaller but not the other way around. In your case with 2 subranges you could do something like: type TAllServerCapabilitiesBase=(uscWhatever scConnected, scCanIssueGUID, lscIsFirebird); TUpstreamServerCapabilitiesBase= uscWhatever .. uscCanIssueGUID;
Obviously that should read
   TUpstreamServerCapabilitiesBase= uscWhatever .. scCanIssueGUID;
Show quoted text 5 lines
TLocalServerCapabilitiesBase= scConnected..lscIsFirebird; Just make sure you put the common values in the middle. Ludo

Reply by email

JC Chu
to Mark Morgan Lloyd: Yes, except that that loses type checking. Mark Morgan Lloyd markMLl .AT. telemetry.co…

If you do not allow clients of your unit to define new elements or change the set values, and what you want to do is prevent, say, accidentally adding an extended element to the set in the base class, you can declare extended elements as class-local constants. Otherwise you will need to add checks in property setters.

Mark Morgan Lloyd wrote 20 lines
JC Chu wrote: > > It is not possible to extend an enumeration type. If you are not > willing to use separate sets to hold common and extended elements, you > can use a generic (not parametric) set type, say SET OF 0..31, that > can hold all possible elements, and define the possible elements as > constants. Yes, except that that loses type checking. -- Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues] _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Best regards, JC Chu

Reply by email

Mark Morgan Lloyd
to Ludo Brands: Obviously that should read TUpstreamServerCapabilitiesBase= uscWhatever .. scCanIssueGUID;
Ludo Brands wrote 40 lines
On 28/12/2012 12:59, Ludo Brands wrote: > On 28/12/2012 12:48, Mark Morgan Lloyd wrote: >> Ludo Brands wrote: >>> type >>> TAllServerCapabilitiesBase=(uscConnected, >>> uscCanIssueGUID,lscConnected, lscCanIssueGUID, lscIsFirebird); >>> TUpstreamServerCapabilitiesBase= uscConnected .. uscCanIssueGUID; >>> TLocalServerCapabilitiesBase= lscConnected..lscIsFirebird; >>> >>> TAllServerCapabiliets=set of TAllServerCapabilitiesBase; >>> TUpstreamServerCapabilities= set of TUpstreamServerCapabilitiesBase; >>> TLocalServerCapabilities= set of TLocalServerCapabilitiesBase; >> >> Thanks, but I was hoping for something the other way round i.e.: >> >> type TCommonServerCapabilitiesBase= (scConnected, scCanIssueGUID); >> >> TLocalServerCapabilitiesBase(TCommonServerCapabilitiesBase) += >> (lscIsFirebird); // INVALID CODE, EXAMPLE ONLY. >> >> TLocalServerCapabilities= set of TLocalServerCapabilitiesBase; >> >> I'd be fairly happy with any solution that did the necessary >> type/range checking at runtime. >> > Enumerations have an ordinal value that starts with 0 by default. > "Combining" enumerations has to make sure the ordinal values are > different. As a result you can go from bigger to smaller but not the > other way around. In your case with 2 subranges you could do something > like: > > type > TAllServerCapabilitiesBase=(uscWhatever scConnected, > scCanIssueGUID, lscIsFirebird); > TUpstreamServerCapabilitiesBase= uscWhatever .. uscCanIssueGUID; Obviously that should read TUpstreamServerCapabilitiesBase= uscWhatever .. scCanIssueGUID; > TLocalServerCapabilitiesBase= scConnected..lscIsFirebird; > > Just make sure you put the common values in the middle.

OK, so if I'm reading that correctly you're putting all possible values into the initial enumeration, declaring subranges of that, and finally declaring sets from the subranges (which might occupy more bits than strictly needed, since the size is determined by the initial enumeration).

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email