views:

631

answers:

7

I kept my hands off Delphi for too long, I guess; busied myself with Java and PHP a lot over the last couple of years. Now, when I got back to doing a little Delphi job, I realised I really miss the conditional operator which is supported by both Java and PHP.

On how many places would you find lines like these in your Delphi programs?

var s : string;
begin
  ...<here the string result is manipulated>...

  if combo.Text='' then
      s := 'null'
    else
      s := QuotedStr(combo.Text);

  result := result + s;
end;

where a simple

result := result + (combo.text='')?'null':quotedStr(combo.text);

would suffice. What I like about this is that it not only shortens the code, this way I also avoid declaring some helper s:string variable.

Why are conditional operators not part of Delphi and - are they ever going to be supported? I noticed there were quite a few language extensions made for the 2009 version of Delphi (generics), so why not add this feature?

+3  A: 

There is no conditional operator in Delphi, and I seriously doubt if there will ever be one but you may never know. You can always issue a request at Embarcadero.

An alternative is to define the Iff function:

function Iff(const ACondition: Boolean; const ATrueValue, AFalseValue: XXX): XXX;
begin
  if ACondition then
    Result := ATrueValue
  else
    Result := AFalseValue;
end;

Where XXX is the desirec type.

Use as:

Result := Result + Iff(combo.text='', 'null', quotedStr(combo.text));

There are several reasons why not to implement the conditional operator. One of these is readability. Pascal (and also Delphi) is more centered on Readability than the C Syntax languages which are more centered on character power (as much information per character as possible). The conditional operator is powerful but (according to some) not readable. But if you look at the (dreaded) with statement in Delphi... (no need to say more). Another reason is that the conditional operator is not required. Which is true. But there is more not required that is still implemented.

In the end it's just a matter of taste.

But if you want just one argument to be evaluated, you can always use the folowing, which violates both the readability as the character power concept:

[overdesignmode]

// Please don't take this that serious.
type
  TFunc = function(): XXX;
function Iff(const ACondition: Boolean; const ATrueFunc, AFalseFunc: TFunc): XXX;
begin
  if ACondition then
    ATrueFunc
  else
    AFalseFunc;
end;

[/overdesignmode]

Gamecat
Unfortunately, this doesn't work like a conditional operator should, as all the functions parameters will be evaluated. A conditional operator should evaluate the test, and then only one of the two remaining expressions.
anon
I've seen this idea utilised before (in PL/SQL)... How would I write an Iff function that would operate with any data type (XXX)?
Peter Perháč
Because Iff is a function both ATrueValue and AFalseValue are evaluated. So a "(o != null) ? o.GetValue() : null" can't be translated to "Iff(o <> nil, o.GetValue, nil)" because the "o.GetValue" would crash.
Andreas Hausladen
I'd guess many have already requested this from Embarcadero... or whoever happens to own it this year.
Peter Perháč
I agree, it is not a perfect substitution. But rewriting the compiler is not that easy done. So we have to work with what we have got. You can, implement some kind of preprocessor. Or stick to the old ways.
Gamecat
Since Delphi recently got the `exit` with return value (which is also not strictly necessary, but has higher "character power") maybe there is some hope for the ternary operator too.
mghie
Is naming such a function as `iff` a common practice? I use to name them `ifelse` functions.
PA
I have seen the use of iff multiple times. But names are often misused and reused to the point of max confusion.
Gamecat
Yes, it isn't required; but then again neither is the "case" statement :)
glob
The name `Iff` is wrong. That's the word for "if and only if," which is nonsense in this context. The name you want here is `Iif`, for "immediate if" or "inline if."
Rob Kennedy
mghie: exit return value could as well be copied from Free Pascal which has had it since 1999 or so.
Marco van de Voort
"Unfortunately, this doesn't work like a conditional operator should, as all the functions parameters will be evaluated."You can "inline" this function. In this case there will not be a real call.
Torbins
No, Torbins, you can't "inline" it. If you inline it manually, you're right back to where you started, with a full-fledged `if` statement. If you rely on the compiler to inline it, it's still going to honor all the function-call-evaluation semantics, which dictate the the actual arguments of a function get fully evaluated before evaluating any of the function's contents.
Rob Kennedy
The "dreaded with" can be used safely and sensibly to make code MORE readable, by eliminating redundant repetition, e.g. with cmbNames do ItemIndex := Items.IndexOf[sSomeName] vs cmbNames.ItemIndex := cmbNames.Items.IndexOf[sSomeName]. As always with dogma, there *IS* a need to say more if we are to have a sensible discussion, rather than just parrot the dogma.
Deltics
+4  A: 

There's a QC report on this (8451) which has a reasonable discussion.

Raised June 2004, and there doesn't appear to be any response from Borland/CodeGear/Embarcadero.

glob
It has 25 votes and a rating of 3.81; probably not enough to make it on the feature list of a new version.
Jeroen Pluimers
+2  A: 

Actually for strings you can use the: StrUtils.IfThen function:

function IfThen(AValue: Boolean;
        const ATrue: string;
        AFalse: string = ): string; overload;

Look in the delphi help wiki: http://docwiki.embarcadero.com/VCL/en/StrUtils.IfThen

It does exactly what you need.

Fabio Gomes
I'll use this, just to try something 'new' :)
Peter Perháč
No, it doesn't. If the ATrue and AFalse values passed to the function are functions, then **both** true and false functions will be executed and evaluated before IfThen() is called. The conditional operator *only* evaluates the expression corresponding to either the true or false branches, depending on the conditional expression.
Deltics
+10  A: 

Such an operator isn't part of the current Delphi version because it wasn't part of the previous version, and demand wasn't great enough to justify the cost of adding it. (You'll find that explanation applies to lots of features you wish you had in lots of products.)

Delphi provides a set of IfThen functions in the Math and StrUtils units, but they have the unfortunate property of evaluating both their value parameters, so code like this will fail:

Foo := IfThen(Obj = nil, '<none>', Obj.Name);

To really do it right, there needs to be help from the compiler. Within the Delphi community, I sense a general dislike of the C-style syntax using a question mark and a colon. I've seen proposals that would use syntax like this:

Foo := if Obj = nil then
         '<none>'
       else
         Obj.Name;

Part of what makes conditional operators so attractive is that they let you write concise code, but Delphi's style of writing everything out makes the above unappealing, even if put all on one line.

It doesn't really need to be in the form of an operator. Delphi Prism provides a compiler-magic function Iif that only evaluates one of its two value parameters:

Foo := Iif(Obj = nil, '<none>', Obj.Name);

You asked why a feature like this wouldn't have been added along with all the other language features added in Delphi 2009. I think that's your reason. There were plenty of other language changes going on that already required delicate handling; the developers didn't need to be burdened with even more. Features aren't free.

You asked whether Delphi will ever have such a feature. I'm not privy to Embarcadero's planning meetings, and I had to send my crystal ball away for repairs, so I can't say for certain, but I predict that if it ever would have such a feature, it would come in the form of Delphi Prism's Iif function. That idea shows up near the end of the discussion in Quality Central, and an objection is made that, as a new reserved word, it would break backward compatibility with other people's code that already defines a function with the same name. That's not a valid object, though, because it wouldn't need to be a reserved word. It could be an identifier, and just like Writeln and Exit, it can be eligible to be redefined in other units even though the one from the System unit is treated specially.

Rob Kennedy
Thanks for contribution, an interesting read. Hope your crystal ball comes back safe and sound and then you could tell us more about the future of ()?:
Peter Perháč
+1 Excellent answer to a difficult question.
cjrh
One nice syntactic effect of the C ternary operator is the elegant concatenation of conditionals, you can write `v=c1?a1:c2?a2:c3?a3:b` current delphi IfThen syntax prevents it.
PA
Whether that syntax effect is classified as "nice" or "elegant" is a matter of some debate, @PA. I find your example to be an inscrutable blob of code. I cannot understand it on the first reading — I can't even *parse* it in one pass. Spaces and parentheses might help. I try to avoid having nested conditional operators.
Rob Kennedy
+2  A: 

There are a number of available simple type handles on the overloaded IFTHEN function.

StrUtils.IfThen(String)
Math.IfThen(Integer)
Math.IfThen(Int64)
Math.IfThen(Double) (Works for TDateTime as well)

This model falls down as shown in the example that Andreas commented on, but for simple types this is more than reasonable. If follows the Delphi/Pascal convention of methods rather than succumbing to the C way of using the least amount of characters as possible.

<mini-rant>Personally I would rather not see a conditional operator (i.e. ?:) introduced in Delphi as I prefer the readability of Delphi/Pascal over C and it derivitive languages. I would prefer to see more innovative Delphi type solutions to something like this than to implement more C-isms</mini-rant>

Ryan J. Mills
mini-rant: I have seen very unreadable code with even very small usage of the ? ternary operator in C-like languages. The main cause is that it is yet another symbol being used, and most people using it forget to add parentheses or indentation for readability. The speed improvements that it can bring are hardly reached: most usage is just a replacement of a single if/then/else, whereas real improvement only can be gained in complex expressions that few people can maintain.
Jeroen Pluimers
A: 

Better yet is an overloaded IIF (inline if) that supports multiple datatypes and results.

General Jackson Tackett
There are already a few IfThen() routines in the StrUtils and Math units. They are not the same as a conditional operator because the IfThen() routines are functions with parameters. All parameters are evaluated when the function is called. Often only 1 parameter is valid so the call to the function will crash. Imagine calling IfThen(false, ClassA.X, ClassB.X) with ClassB being nil. A conditional operator should only evaluate the part that is determined by the condition and ignore the other part.
Joe Meyer
+2  A: 

I would prefer them to to implement lazy evaluation and it will be more powerful and can be used in different scenario. See detail as below link

http://www.digitalmars.com/d/2.0/lazy-evaluation.html

Cheers

Pham