
Embarcadero is working on a new version of Delphi (and RAD Studio) codenamed Ganymede and currently in Beta. In this blog post and others that are going to follow, we want to start introducing some of the exciting new features of this release. This blog post is based on a pre-release version of the RAD Studio software. No feature is committed until the product’s GA release.
Among other improvements to the Delphi language and its compilers, the RAD Studio 13 release will introduce a conditional operator (or ternary operator) to the Object Pascal language, for the first time. This has been one of the most requested language enhancements by customers for quite some time and this feature is available in the current Ganymede beta for testing.
Table of Contents
Delphi now has a Ternary Operator using a new form of the If keyword
A ternary or conditional operator is an operator which behaves like an if statement, with a condition and two possible values. In many other programming languages, the ternary operator is indicated using the ?:
syntax. In Delphi, we want to preserve as much as possible a familiar and Pascal-oriented syntax, so we decided to use the if
symbol as an operator. In other words, if
can now be used to indicate a statement or an operator, depending on the position in the source code.
This is an example of a simple assignment expression in two versions, the first based on a traditional if statement and the second on an if operator:
1 2 3 4 5 6 7 8 |
// classic if statement if Left < 100 then X := 22 else X := 45; // assignment with if operator X := if Left < 100 then 22 else 45; |
The key difference is that the if operator can be used as part of any expression, as follows:
1 |
ShowMessage (if Left < 100 then 'Small' else 'Big') |
Here you can see this code in the editor of the 64-bit version of the RAD Studio IDE, using the RAD Studio 13 beta.

The if operator in action in the RAD Studio 13 editor (in the 64-bit version of the IDE)
What are the compatibility rules of the Delphi Ternary Operator?
There are specific rules in terms of the coherence among the types of the two sub-expression. In short, they have to be of the same type, or a directly assignable type. If not you’ll get a compiler error, like in this case:
[dcc32 Error] Unit31.pas(38): E2010 Incompatible types: 'string' and 'Integer'

An example of an if operator incompatibility error
There is an extremely long table in the beta documentation with the different type
combinations you can use in the new if
expression, and the resulting type of the expression for each of these combinations. I’m not reporting it here as it’s a couple of pages long and goes to a level of detail not needed for this introduction.
What is the Order of Priority for the Delphi Ternary Operator?
When using the if-then-else operator within an expression, notice how other operations (e.g., addition) have higher priorities, which can lead to unexpected errors. Use extra parentheses, like you often have to do with low-priority Boolean operators. Let’s look at this code:
1 |
ShowMessage (if Left < 100 then 'Small' else 'Large' + 'Nice') |
What’s going to be the output if Left
is less than 100? It is “Small” or “SmallNice“? It’s the former, because the +
has higher priority making it like:
1 |
ShowMessage (if Left < 100 then 'Small' else ('Large' + 'Nice')) |
if you always want the additional word to be added, you should use:
1 |
ShowMessage ((if Left < 100 then 'Small' else 'Large') + 'Nice') |
RAD Studio 13 will bring in a number of other new features and modernizations to the Delphi language
While this won’t be the only change to the Delphi language in RAD Studio 13, it is one of the most prominent and requested changes to the language we are going to introduce. There are other new operators coming along, and some new and expanded compiler directives. Overall Delphi 13 (part of RAD Studio 13) is going to be a very important release for the evolution of the Delphi Object Pascal language. Stay tuned.
This blog post is based on a pre-release version of the RAD Studio software. No feature is committed until the product’s GA release.

Why not download a free trial of RAD Studio today and see why we think it’s the fastest, easiest, and most efficient way to create cross platform apps that work on Windows, macOS, Linux, iOS and Android from a single code base?
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition
Nice!
30 years of Delphi and still in its infancy. Long live… 🙂
Well, yes, although we prefer to think of it as “still learning, still growing”. Part of growing and maturing is embracing new ideas and adopting the best ones so that we can improve. Delphi is very much alive and striving to better itself. 😁👍
We listen to compliments, we listen to criticism, we listen to suggestions. A good idea is a good idea and, where possible, we will always act on them. There are very few languages and organizations out there who genuinely do this, and I’m really pleased to be a very small part of making that happen. Every member of the Embarcadero team feels like this. It transcends ‘just work’.
Thank you, Guido, and yes, long live Delphi! 🖖
Hi Ian, yes exactly, the comment was meant as a compliment in the “still growing” sense, in contrast to beliefs that “old” things must be obsolete, particularly in the Information Technology world.
I recently wrote an article “33 Years JPEG: Ubiquitous Presence and Still in its Infancy”.
The comment is derived from that title.
In the case of JPEG everybody can see that it works, but nobody seems to know why.
I know why it works: Because it has substance and potential for further growth.
That’s why I am happy to work on it, and yes I can see similar enthusiasm in your and your team’s work on Delphi and RAD, too,
I plan to do more support for RAD/Delphi in the future, have just started in the latest release…
You can find the article on the “Independent JPEG Group Reference Site” in the News section.
I have also covered RAD/Delphi in the previous two articles about Integrated Development.
Good luck!
Regarding the “long live” phrase:
I wanted to make sure that I write it correctly, and my favorite search engine (Bing) came up with Taylor Swift’s song.
Highly recommended for inspiration…
Will the 32 and 64 bit compiler also utilze the cmov opcode for this?
Do you think it should?
I mean c compilers do it… why not. The performance impact is there (at least a factor of 2 of a test that does just a Max operation). The first CPU that had the cmov was the Pentium Pro. At least on 64 bit environments it’s granted that the instruction is there.
It’s a really great addition!
Just keep it getting better and better!
And don’t forget to update the coding formatting tool to be fully compatible.
I wouldn’t have thought a ternary operator was such a requested feature, I intentionally avoid their use most of the time. Just the same I’m looking forward to innovations coming in the next release =)
Thanks Travis – I’m looking forward to version 13 too. Many more new goodies coming which we’ll write about as we get closer to being able to release it.
The Ternary Operator really was something that hundreds of people asked for over the course of several years. There are other features too that get mentioned regularly but the Ternary Operator for Delphi was the clear leader in popularity. We do listen to all suggestions and it’s nice to see things like this bubble up to the surface. It’s not for everyone and there was (and is) a lot of discussion on how to do it in a ‘Pascal like’ way along with much technical to and fro surrounding what should happen with various types and nil objects. This is one of the benefits of engaged and passionate beta testers – they help employ the wisdom of crowds effect so we reach a consensus where our thoughts are amplified and combined with beta tester’s discussions.
There’s more coming with RAD Studio 13 – it’s a HUGE release full of some dramatic new things and a large swathe of improvements.
Starting over 30 years ago with Pascal on a Schneider CPC I dont’t see that this is a “PASCAL”-Feature.. It makes code less readable without any advantage and Pascal’s strength lies in its clarity, especially when compared to languages that rely on cryptic syntax.. This feature is (IMHO) only syntactic sugar. And too much sugar is a drug, too. The good news, I dont have to use it 🙂 …and curious about what else is coming. 🙂
What is the plan for XE 12.3 after XE 13 is released?
What the diference between Ternary Operator and IfThen() ?
The Ternary Operator can be used in expressions whereas
IfThen()
acts more like a compact conditional statement.IfThen() being a function can also be used in expressions, but the problem is when using expressions as parameters, because *all* parameters (also the non-true) are evaluated *before* executing the function, which may by unwanted.
The conventional conditional statement and ternary operator prevent that: The non-true part is *not* evaluated.
Found following example in a forum for conditional dereferencing a pointer:
IfThen(Assigned(entry), entry^.bc, ”)
This code creates access violation.
The condition is meant to check for accessibility, but the illegal access happens anyway in this case. Ternary operator is the solution.
If I use
IfThen
, both functions will be called/evaluated.X := IfThen(Left < 100, HasCollateralEffectA(), HasCollateralEffectB());
Does this new operator evaluates both expressions (then and else) ? Like:
X := if Left < 100 then HasCollateralEffectA() else HasCollateralEffectB();
The easiest way for me to answer this is to show you an example of the ternary or conditional operator in action:
The answer is, as you can see, only the appropriate part of the expression is evaluated, not both.
What about nested ternary operator? What is the order of priority if nested?
Is nested ternary operator even supported in this case?
I imagine you’d use brackets around the nested conditional ternary expression to make things more explicit, similar to what Marco suggested in the blog post.
hi eu sou umas das centenas de pessoas que fez essa solicitação e estou feliz em ser atendido!
https://embt.atlassian.net/servicedesk/customer/portal/1/RSS-3494
[Translation: Hi, I’m one of the hundreds of people who made this request and I’m happy to be served!]
That’s great! Thanks for making the suggestion, we really do appreciate it. 🙂
I’m not fan of the ternary operaor, it’s one of construct I hate the more in C/C++ (and other Cish languages like php, …).
I think this is bastardizing (sorry for the word) the Pascal language. Pascal is clean language, its constructs are really clean and easy to read. You are making it more C++ like and I hate that. I hated the fact you add the possibility to define variables between instructions, in Pascal we define variables in a declaration bloc, not anywhere else. This is killing the spirit of Pascal language.
For ternary operators, Delphi is rich enough with its generics to create a more Pascal way of doing it without destroying the language elegance.
I used to use something like:
unit TernaryGenerics;
interface
function IfThen(const Condition: Boolean; const TrueValue, FalseValue: T): T; inline;
implementation
function IfThen(const Condition: Boolean; const TrueValue, FalseValue: T): T;
begin
if Condition then
Result := TrueValue
else
Result := FalseValue;
end;
end.
And you can use it like
uses
TernaryGenerics, SysUtils;
var
i: Integer;
s: string;
d: Double;
begin
i := IfThen(5 > 3, 100, -100);
// i = 100
s := IfThen(Length(‘Hi’) = 2, ‘Two chars’, ‘Other’);
// s = ‘Two chars’
d := IfThen(i < 0, -1.23, 4.56);
// d = 4.56
Writeln(Format('i=%d, s="%s", d=%.2f', [ i, s, d ]));
end;
This keeps Delphi a true clean Pascal language and we really don't need a construction that add such complexity in type system and compatibility … above code works the same as any Pascal language function with all proven and well defined and understood type compatibility related rules..
Sorry I don't want to be rude, it's just my own opinion about those new language enhancements.
Thanks for all your work.
Regards
Wow that’s a long comment! 😁👍
You are not being rude, you’re just passionate about Delphi and Pascal, same as I am and my colleagues.
I understand what you’re saying that the Ternary operator is not for you. I totally get it. But, on the flip side, there have been many hundreds of people asking for it and putting across their own justifications for why it was necessary to them. The same was true for inline
var
declarations – there was an enormous amount of discussion about that language feature and, personally, when they first came out I hated them with a passion for not being ‘Pascal-like’. Now, a few years further on, I find them very useful, especially the type inference that they can provide.Delphi becoming more like C++? No, that I do not agree with. We chose the syntax we did for the Ternary operator deliberately to balance usability and succinctness against readability. I am an old-time Pascal guy so I still use, for example,
Inc(MyVariable);
instead ofMyVariable := MyVariable + 1;
because it’s more ‘Pascal’, and succinct. Looking at code out there, including some of our own examples at Embarcadero, I realize I am probably one of the very few people who useInc()
even though it’s an elegant structure.But Niklaus Wirth invented Pascal way in advance of things like Windows, Unicode, advanced memory management, object orientation, and other cool stuff which necessitates the embracing of language concepts like Generics. The language has to evolve along with the rest of Computer science, and we also have to listen to our users and pick the things they feel they need and which we can incorporate successfully. We think long and hard before introducing new language features and we involve all sorts of people to try and ensure that our thoughts on the subject are in keeping with those of the majority of our users, are possible to implement, and are done so in a way that stays as close to Wirthian principles while embracing the evolution of software development to keep us current.
I know, for some, a Ternary operator is going to be unwelcome (and they can choose to pretend it doesn’t exist and never use it) but for a substantial swathe of coders it’s going to be a winner.
Thanks for making such a thoughtful and passionate comment. I mean that.
I don’t think I’ve ever seen a feedback form that asks: “Do you really need this feature?”
Just because many people request something through the ticket system doesn’t necessarily mean it’s the right direction — especially when the silent majority hasn’t been heard.
I totally agree with Ahmed: yes, it’s less work to write. But in my opinion, that alone is not a valid argument for changing the language.
If the goal is to write less or faster, that’s exactly what IDEs are for.
You only write a line of code once — but it gets read many more times.
For a second person (or even yourself after some time), these lines take longer to understand due to their high code density.
Well, we don’t just base our thoughts on feedback forms, of course. We (the PMs, me, SCs, support, and other customer-facing staff) speak to and work with a great many Delphi developers in all sorts of circumstances including one-to-one conversations, community events, user groups, forums, social media. Also, people like Marco and I have been, first and foremost, Delphi developers for many years since at least version 1 and in Marco’s case even before that. That’s not even taking into account the 200+ MVPs and many hundreds of tech partners around the world too.
The inclusion of a Ternary operator has been something raised to us repeatedly by a wide variety of people. The fact you can comment on it on this blog and probably know my email address off by heart through Developer outreach things like webinars means the “silent majority” is no such thing. You can quite literally contact us in a variety of different ways either through things like email, blog comments, and in person too. I will be at two events in Germany in September, one in Poland, preceded by one in Brazil, and followed by another event in Florence. If you ever want to have your voice heard, we absolutely make it a no-brainer to let us know – good or bad, happy or sad.
We are definitely confident that this feature is one which a massive overwhelming number of people wanted – but like many things, it’s optional, of course, you can choose to never use it and safely keep using Delphi the way you want, the way that suits you.
Your usage examples (and those given by Marco) use only constant values after the condition.
But the problem is in other cases as mentioned in this thread.
An older version of the JPEG reference code (written in C language) used following code:
/* Precalculate which table to use for each block */
entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no];
entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no];
This had to be corrected in order to secure the array access as follows:
/* Precalculate which table to use for each block */
entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no];
entropy->ac_cur_tbls[blkn] = /* AC needs no table when not present */
cinfo->lim_Se ? entropy->ac_derived_tbls[compptr->ac_tbl_no] : NULL;
This is the most elegant solution and is the current JPEG reference code.
The proposed Delphi solution looks just as well and appropriate to the Pascal language to me.
I agree with what Ian said: You don’t have to use it, but it is good to have the option.
Regards
Guido
JPEG developer
My example was deliberately simple to illustrate that evaluation is short-circuited. The actual operator itself allows a wide range of argument types (the beta doc has a two-page table of them along with how they would evaluate). They include things like anonymous methods, interfaces, instance variables, class references etc.
Ian, your example is great, I was replying to the examples given by Ahmed.
Mabe it’s a bit confusing to relate in this long thread. 🙂
I think I have made my opinion clear: Well done, go ahead!
But how to do that:
var z := if y = 0 then 0 else x / y;
using IfThen()?
This could only be done, if Delphi had “lazy evaluation” of parameters. Which would of course be nice…
function IfThen(const Condition: Boolean; [lazy] const TrueValue: T; [lazy] const FalseValue: T): T;
Joachim, I have good news for you – the implementation of the new Delphi Ternary operator *does* do lazy evaluation which is one of the other advantages it has over the
IfThen
function.Tenary operator is cool, and I have a question: when will you add more difficult to implement changes to the language, such as:
Contracts (Interface without reference counting)?
> Contracts (Interface without reference counting)?
We do have several things we are looking at which are trickier to implement. There have been some very lively discussions about even more obvious and popular things like the Ternary operator.
You can also raise a ticket as a feature request on our Quality Portal. This is how the new Ternary operator came about – a whole raft of people wanted it, and we found we could implement it in RAD Studio 13, so we have. If Contracts are something people want in sufficient numbers, we’d definitely consider them – a good idea is a good idea.
You can use Interface and just not use the reference counting, if you want.
https://docwiki.embarcadero.com/RADStudio/Alexandria/en/Not_Using_Reference_Counting
I wish this was like the Python ternary operator; it would read better.
For example, instead of
X := if Left < 100 then 22 else 45;
have it be
X := 22 if Left < 100 else 45;
This is an example for another insane solution similar to the IfThen function.
In security related application as mentioned it is important to check the condition *first*, *before* evaluating any other term, and I want to read it in that way.
This security related application may also be the reason why Embarcadero put such high priority on the feature.
The Swift language does it in the C way, which is okay.
Only the Pascal language lacked the feature so far.
Well done, Embarcadero, go ahead!
A Real Conditional Ternary Operator Must Short-Circuit Evaluation
As a long-time Delphi developer, I’ve always felt that Delphi lacks what I would call a real conditional ternary operator — not just in syntax, but in behavior.
Let me give a practical example that still fails in Delphi 12 (latest update):
delphi
Copy
Edit
type
TMyTest = class
private
fMyField: string;
public
property MyField: String read fMyField;
end;
var
LSomething: TMyTest;
begin
LSomething := nil;
try
Writeln(IfThen(Assigned(LSomething), LSomething.MyField, ‘Not Assigned’));
except
on E: Exception do
Writeln(E.ClassName, ‘: ‘, E.Message);
end;
Readln;
end.
Despite Assigned(LSomething) returning False, this still raises an Access Violation. Why? Because both the True and False parameters in IfThen are evaluated eagerly, before the function is called — regardless of the condition.
This is not how a true conditional (ternary) operator should behave.
In a real ternary expression, such as in C/C++ or C#:
condition ? expr1 : expr2,
only the selected expression is evaluated.
This allows for safe execution paths that depend on the result of the condition, even when the unselected branch would raise an error.
In Delphi, we still need to write verbose code with if…then…else just to avoid such side effects. This becomes especially limiting when we want to use concise expressions (inlining logic inside parameters or property assignments, for example).
I truly hope that in Delphi 13 and beyond, Embarcadero introduces a genuine conditional operator that:
Has proper short-circuit evaluation semantics,
Is fully type-aware (not just string overloads), and
Can be used inline, safely and expressively.
Such a feature would be a welcome and modern addition to the Delphi language.
Thank you to the Embarcadero team for continuing to modernize Delphi!
Well, I have some good news for you – the new Ternary operator works in exactly the way you want it to and not like the IfThen() function. If you look at the screenshot in my comment above you can see that the arguments are not evaluated until they are selected (short circuit evaluation) – just as it works in C# and some other languages.
DeveloperStatus := if Delphi13TernaryWorks then ‘ready and done!’
else if StillWaiting then ‘medium patience left’
else ‘bloody tired of if-then-else’;
Understood. This beta cycle is a long one and there has been a lot of extremely useful feedback from all sorts of areas about this and various other suggested features. The reason we keep the Beta under NDA is not everything included will make it into the GA (final) release, so we don’t want people to get disappointed if something isn’t quite fully baked and needs to get pulled so we can try to get it improved. I know we don’t always get it right but there are some Herculean efforts going on to always aim to improve quality, stability, and usefulness.
ARM compiler for Windows?
Right now, we can’t announce anything more about a Windows ARM Compiler. We know it’s high on people’s lists, including large organizations like Microsoft in order to better serve the Windows ARM community with ARM-native apps.
The fact that Windows on ARM 32-bit was a failure made people reluctant.
The Arm64 Windows platform is trustworthy only since November 2024, when Microsoft first published a general download source beside the x64 version.
So the first generally available version is the Windows 11 2024 Update (Version 24H2), which is also the first Windows 11 LTSC (Long-Term Servicing Channel) version.
I have Windows 11 ARM running in a virtual machine on a MacBook with Apple silicon.
It works very well.
So yes, ARM compiler for Windows is welcome, and also native IDE.
Very nice! Great addition! Adds a very reasonable code simplification that is commonly used in other languages. Thank you!
Thank you. But is this new feature recognized by the LSP? Some of us are having real issues with the LSP restarting multiple times per second and then becoming unresponsive. Personally, I fear this could be another obstacle to trip the IDE. Please restore refactoring and fix IDE instabilities before adding any more language features. How many years since inline var declarations were introduced? They still break refactoring.
I was one of the many people who requested it and its great to see it finally getting added!
There are quite some situations where it would make code cleaner and more robust.
Syntax looks quite odd and wordy at first, but that’s how most of the Delphi code looks 🙂
Well, blame Niklaus Wirth for the wordiness of Pascal! 😉 Yes, you’re right though, we deliberately chose a keyword which was ‘Pascal-like’ to keep in with Delphi and Pascal’s excellent readability.
I’m glad we could get it added, thanks for being one of the ones who requested it! 😁👍
@IanBarker What has happened with Structure view in the IDE in Delphi 12?
It stopped showing nice tree structure of the unit with classes and methods and etc. Now it shows some odd new kind of a anemic tree without many things like visibility modifiers and proper sorting. At the same time, Options>UI>Structure still shows the options only for the old Structure. Is that a fluke or a new ongoing development/migration? Old Structure was quite fine and we used it a lot during development to navigate around class methods.
We’re revisiting and improving this area for future versions. More on this shortly! 🙂
Thanks for the answer! Good to hear that this is intentional change and not a regression. I hope the new one will have the same basic functionality intact.
It is unfortunate that the revisit leaves it unusable state (instead of being parallelly available) for more than half a year now though.
I do miss this handy methods navigation tree a lot in my work. I’ve tried some alternative IDE plugins, but they are too overcrowded with visual noise, infos and options.
As Delphi Evolves to new Versions, why don’t we have Pascal as a scripting language in Brewers
Brewers?
Personally, I like the syntax and it’s something I’ve found lacking in Delphi having used a lot of Java and C/C# over the years.
Finally, glad to see it! The syntax is traditionally pascal, so while it is bulky, I fully embrace it as following the intent of the pascal language itself! That said, it would be nice to also have a shorter syntax for this and lambda like expressions ( the extra typing is very explicit, but can get in the way of readability for anonymous methods)
I look forward to see what else gets added. It would be nice to see enough syntax added to allow for things like streams like Java etc.
I realize we are unlikely, even after 2+ decades, to catch up to C# with Linq, but every step forward is good for the future of Delphi.
Personally I think the short syntax in other languages is the most powerful feature of the ternary operator, because there are *NOT* much language elements around the actual values, which makes especially mathematical routines much better readable. The syntax now used in Delphi is ‘pascal-ish’, but has not many advantages over:
if Left < 100 then X := 22 else X := 45;
Of course you can use it in expressions and the like, but as clean code does not pack one expression after another, I do not see much of an advantage. Sorry to say that…
But nevertheless I like to see, that the Delphi language still evolves. And I hope, that there will be other extensions, which are more useful for me.
New target WebAssembly PLS
nice, it feels natures for if/then/else expressions to be able to return a result (may have even suggested it in the past, don’t remember), but how about also adding ?. and ?? operators too to ease porting code and helping write cleaner / less-verbose (and thus tiring to read or glance-debug) code?
btw, wouldn’t mind also for a ? prefix before any boolean operator to do null checking for left operand (and return false), e.g. expression (x ?>= 0) would be (x nil) and (x >= 0). Could even extend it to ? suffix probably to do null checking for right operand. And maybe even allow both prefix and suffix ? to guard both operands for nil
seems C# apart from ?? also has a null-coalescing assignment operator (?=, that could be ?:= in Delphi) which is not widely used in my experience, but looks interesting https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-coalescing-operator
I kinda like the new operator, but I can also see it’s fall/failure: it will be hard to expand the code later/multi line/statements (?), but for some little things it could make the code a bit more compact…