Add enumeration handling differences to FPC/Delphi wiki page
Closed this issue · 1 comments
Hi Michalis!
I'd like to contribute a section about enumeration handling differences between FPC ObjFpc mode and Delphi to your wiki page "Some differences between FPC ObjFpc mode and Delphi".
I've been exploring Pascal variants (Delphi → FPC → Ada) and discovered some practical differences that aren't currently documented in your excellent wiki.
Proposed Addition: Enumeration Handling
Delphi Pascal vs Free Pascal Compiler (FPC): Enumeration Differences
Overview
This document compares how Delphi Pascal and Free Pascal Compiler (FPC) handle enumerations, highlighting key differences in syntax, functionality, and behavior.
Core Enumeration Declaration
Both Delphi and FPC support the same basic enumeration syntax:
type
Week = (Mon=1, Tue, Wed, Thu, Fri, Sat, Sun);
String Representation
Delphi Pascal
- Requires manual lookup arrays for string conversion
WriteLn(enumValue)outputs ordinal values, not names- Must create constant arrays to map enum values to strings
const WeekNames: array[Week] of String = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun');
var
today: Week;
begin
today := Fri;
WriteLn(WeekNames[today]); // Outputs: Fri
WriteLn(today); // Outputs: 5 (ordinal value)
end;
Free Pascal Compiler (FPC)
- Built-in string conversion supported
WriteLn(enumValue)directly outputs the enumeration name- No lookup arrays required
var
today: Week;
begin
today := Fri;
WriteLn(today); // Outputs: Fri (enum name directly)
end;
Successor and Predecessor Functions
Delphi Pascal
- Supports
succ()andpred()functions for enumerations - Provides convenient sequential navigation
- Runtime error occurs at boundaries (e.g.,
succ(Sun)fails)
var today, tomorrow, yesterday: Week; begin today := Fri; tomorrow := succ(today); // Works: returns Sat yesterday := pred(today); // Works: returns Thu
// This would cause a runtime error:
// tomorrow := succ(Sun); // Runtime error!
end;
Free Pascal Compiler (FPC)
- Does NOT support
succ()andpred()on enumerations - Requires manual ordinal manipulation using
Ord()and type casting - Forces explicit boundary checking
function ShowTomorrow(Day: Week): Week; begin if Day = Sun then Result := Mon // Explicit wrap-around handling else Result := Week(Ord(Day) + 1); // Manual increment end;
function ShowYesterday(Day: Week): Week;
begin
if Day = Mon then
Result := Sun // Explicit wrap-around handling
else
Result := Week(Ord(Day) - 1); // Manual decrement
end;
Boundary Handling
Delphi Pascal
// Potential runtime errors at boundaries today := Sun; tomorrow := succ(today); // RUNTIME ERROR!
// Must check boundaries manually:
if today = Sun then
tomorrow := Mon
else
tomorrow := succ(today);
Free Pascal Compiler (FPC)
// Forces explicit boundary handling from the start
function NextDay(day: Week): Week;
begin
case day of
Mon: Result := Tue;
Tue: Result := Wed;
Wed: Result := Thu;
Thu: Result := Fri;
Fri: Result := Sat;
Sat: Result := Sun;
Sun: Result := Mon; // Explicit wrap-around
end;
end;
Array Indexing with Enumerations
Both Delphi and FPC
Both support using enumerations as array indices:
const WeekNames: array[Week] of String = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun');
var
today: Week;
begin
today := Fri;
WriteLn(WeekNames[today]); // Works in both
end;
Trade-offs Analysis
| Feature | Delphi | FPC | Winner |
|---|---|---|---|
| String conversion | Manual lookup arrays | Built-in WriteLn() | FPC |
| Successor/Predecessor | succ()/pred() functions | Manual Ord() manipulation | Delphi |
| Boundary safety | Runtime errors possible | Forces explicit handling | FPC |
| Code verbosity | More concise for sequential ops | More verbose but safer | Tie |
| Array indexing | Full support | Full support | Tie |
Practical Implications
When to Choose Delphi Approach
- Sequential enumeration operations are common
- Performance is critical (avoid function call overhead)
- Working with legacy Delphi codebases
When to Choose FPC Approach
- Safety is paramount (prevent runtime boundary errors)
- Debugging and logging are important (built-in string conversion)
- Working with circular/wrapped enumerations (days of week, etc.)
Conclusion
Delphi favors convenience and traditional Pascal behavior with succ()/pred() functions but requires manual string handling and can have runtime boundary issues.
FPC prioritizes safety and built-in functionality with automatic string conversion but requires more explicit code for sequential operations.
Both approaches have merit depending on the specific use case and safety requirements of your application.
The text proposed in the issue description above is AI-generated (by ChatGPT or similar) and has multiple factual errors.
It took me almost 2h to write this answer, because I wanted to explain to you what's wrong. As a human speaking to another human: please read this.
Key point: don't use AI like this
I go into details below. Let me start with a key point:
Please don't send AI-generated issues / pull requests. Please don't trust what AI tells you, it's often completely wrong (as demonstrated here). Always test your claims by actually using the software (e.g., testing code snippets with FPC and Delphi, in case of this).
Please realize I answer to this manually, I'm a human typing this answer, no AI is writing this. And I write this super-long answer because I value you and I think you genuinely wanted to help the project. But this is not the way to help the project. Using AI to write such text is a way to get yourself confused.
The right way to learn is:
- Play with Pascal, Castle Game Engine, etc. yourself,
- explore the differences between 2 compilers by actually using them and testing the details.
And yes, you can even use AI in a sensible way, also with Pascal. I give some advises below.
Overview of mistakes in proposed text
I point some of the concrete mistakes below. Let me give an overview first:
-
Literally all sections have at least one important fact just wrong. Test them in actual compilers, FPC and Delphi -- you will see.
-
It all starts with a misleading example with explicit assignment
Mon=1making this enum type a bit special, and no prose actually notes this fact.Even if the facts in text would be correct (they are not!) this would be rather confusing example (for developers new to Pascal), as usually you let the compiler assign all values in the enum type (and they start from 0). Calling this example "same basic enumeration syntax" is misleading, this actually shows a seldom-used special case of enum type.
-
The summary sections "Trade-offs Analysis", "Practical Implications" and "Conclusion" are full of wrong statements. Because they are based on mistaken claims in previous sections, and they add some new mistakes too.
-
The whole text looks like "AI slop", and it is an "AI slop", I'm afraid. That is: it looks very professional (analyzing trade-offs etc.)... but it's simply wrong, with multiple incorrect assumptions + combined with misleading example + leading to multiple incorrect conclusions.
A message to the contributor
@chikega I'm sorry. I know you're a long-time supporter of Castle Game Engine and of things I develop. And I don't like rejecting contributions, AI-generated or not. This was AI-generated, but I believe you also put time into doing this, you just (incorrectly) thought that using AI is the most optimal way of doing this.
This is an example of how one should not use AI. You trusted AI to write something, and it made a mess. There are nuggets of truth between the incorrect statements, but there are too many incorrect statements to use this prose, in my opinion. (Note: by "AI" below I mean "current, popular LLM-based AI products").
How to use AI better
My general advise to using AI, voiced also in some Discord threads:
-
You must be the one in the steering wheel.
-
Because AI absolutely will make mistakes, sometimes very critical mistakes, important facts will be just completely wrong. AI just puts together words it found on the Internet (GitHub, StackOverflow etc.) into something that "looks right, sounds plausible".
-
And AI will be super-confident with presenting you these mistakes as truth. It was trained to sound confident.
-
If you use AI, always test everything it tells you.
- Just like you would do with results from any search engine (Google, DuckDuckGo) etc.
- Except with search engines, when it says something wrong -- it comes directly from some human being wrong (deliberately or by mistake). In case of AI, it will say wrong things because it's just stupidly guessing.
- And in case of search engine, you know "the source" of the information. AI will not tell you the source, because it's a combination of multiple sources, and also because telling sources is sometimes a premium feature.
- So just test everything.
-
Don't let AI do high-level stuff for you.
- Because, again, AI will be just wrong, with high probability.
- Or, even if AI would be right (and it is not right in this case!), the stuff it could come up with could be irrelevant, talking about details that are not important and omitting things that are.
- The high-level stuff, the issues you want to talk about, should come from you.
If anything, AI can help you refine some things, like improve your English spelling or grammar. Start with this. Sorry it sounds less impressive than just using AI to write a book / software. But AI is too stupid to write a book / software. It can only help YOU write a book / software.
To be clear, I use some AI tools myself, code completion, agents. It's sometimes just productive. But I'm always wary that AI makes mistakes, and yes it makes them very often. If you don't have knowledge/time to "filter out" these mistakes, then using AI in a given field is not a good idea.
Test the compilers
In this case, you have access to the compilers. FPC is open-source and free. Delphi (Community Edition) is also free.
Details what is wrong
OK, let's go with details:
-
Factual error about Delphi:
"""
WriteLn(enumValue)outputs ordinal values, not names
"""No, that's not true. Same goes for example below with line:
WriteLn(today); // Outputs: 5 (ordinal value)No, this will not output 5 with Delphi. This will just not compile. I just tested it with Delphi 12.3. You can test it yourself too, there's a free Community Edition version of Delphi.
-
Important omission in the context of above: misses
GetEnumName, which works with both FPC and Delphi. FPC just allows alsoWriteln(enum). -
Factual error: while out of bounds enums may cause run-time error (with both compilers), the Delphi example is actually detected as error at compile-time.
// This would cause a runtime error: // tomorrow := succ(Sun); // Runtime error!The above comments are incorrect. Try it in Delphi -- it will actually not compile.
Moreover, you can try it with FPC too (that's right, it supports
Succ/Pred), it also detected it as compile-time error. -
Misleading example: the example at the beginning of the text starts with
Week = (Mon=1, Tue, Wed, Thu, Fri, Sat, Sun);which has some limits in FPC with non-Delphi mode, because it's a special enum, with explicit assignment
Mon=1.4.1. Not using Pascal conventions is also poor.
Tfor type name, 2-letter prefix for names, or scopedenums. I discuss them in https://castle-engine.io/modern_pascal . -
Factual error: claims that FPC doesn't support
Succ/Pred.Likely because AI was confused by its own misleading example above, with
Mon=1which has special behavior in non-Delphi modes of FPC.{$R+} {$Q+} type Week = (Mon=1, Tue, Wed, Thu, Fri, Sat, Sun); var today, tomorrow, yesterday: Week; begin today := Fri; tomorrow := succ(today); // Works: returns Sat yesterday := pred(today); // Works: returns Thu end.
This doesn't compile with
fpc -Mobjfpc Project1.dprbut it compiles withfpc -Mdelphi Project1.dpr. That's because the enum type is special with thatMon=1, see above. This is a "nugget of truth" hidden in that prose, FPCObjFpcmode indeed does not supportSucc/Predon enum values with explicit assignments like Mon=1.Once we change
Mon=1to justMon, FPC will compile it with bothfpc -Mobjfpc Project1.dprandfpc -Mdelphi Project1.dpr.Note that above I spend my time analyzing "why was AI confused". This is exactly something on which we should not waste our time on. AI is just guessing, AI is repeating stuff from the Internet, randomly meshed to "just look plausible".
-
Misleading naming: You wanted to compare
ObjFpcvsDelphimode, and above "nugget of truth" is indeed about it. But the AI text doesn't communicate it nicely, speaking about "Delphi Pascal" and "Free Pascal Compiler (FPC)" (forgetting that FPC hasDelphimode). -
Factual error or very misleading: the section "Boundary Handling" actually doesn't show any FPC vs Delphi difference. As said above, they both handle boundaries. The 2 pieces of code misleadingly marked FPC and Delphi actually mean the same for both FPC and Delphi, I mean you could use both pieces of code with both FPC and Delphi.
Again, the "normal" way to do this is to use
WeekwithoutMon=1and just usingSuccwith both compilers. Noone writes code like in "Free Pascal Compiler (FPC)" section (NextDaydoing full mapping), noone really needs to write it like this, even if it is possible (with both FPC and Delphi). -
Factual errors on top of factual errors: the sections "Trade-offs Analysis", "Practical Implications" and "Conclusion" are based on factual errors pointed above, so are all wrong.
I also note a new factual error: sentence "Performance is critical (avoid function call overhead)" is some nonsense. I think it's because AI example for FPC defined a
function NextDay(day: Week): Week;while the equivalent example for Delphi didn't define a function (but it should, it was just a mistake)?And the "Winner" table again confuses "FPC" with "FPC ObjFpc mode" and "Delphi" with "Delphi or FPC in Delphi mode".
-
Misleading overall: As said above, nothing mentions that all important differences ("nuggets of truth") here come from
Mon=1(enum with explicit assignment).The one true observation here is a difference between "enum with explicit assignment handling in FPC ObjFpc mode" vs "enum with explicit assignment handling in FPC Delphi mode or Delphi". Presenting it as "different enum handling between FPC and Delphi" is wrong.