Discussion:
Delphi equivalent to C ?: ternary operator
(too old to reply)
Scott
2006-03-05 03:29:22 UTC
Permalink
Does Delphi have an operator similar to C's "?: ternary" operator?

Example: i := (n > 0) ? sum div n : 0

In longer form, the above would look like this:

if n > 0 then average := sum div n
else average := 0;
Nicholas Sherlock
2006-03-05 04:27:08 UTC
Permalink
Post by Scott
Does Delphi have an operator similar to C's "?: ternary" operator?
No. There are some functions that can sometimes be used as replacements,
introduced, I think, in Delphi 6. These are the IfThen() series of
functions. The major disadvantage over a real ternary operator is that
both the 'false' and 'true' values will be evaluated regardless of the
value of the boolean. This would make it useless for the specific
situation you describe.

An IfThen() might be:

function IfThen(b:boolean; aTrue:integer; aFalse:integer):integer;
begin
if b then
result:=atrue
else
result:=afalse;
end;

Cheers,
Nicholas Sherlock
J French
2006-03-05 08:02:11 UTC
Permalink
Post by Scott
Does Delphi have an operator similar to C's "?: ternary" operator?
Example: i := (n > 0) ? sum div n : 0
if n > 0 then average := sum div n
else average := 0;
A very contrived example :-

Var
J, N :Integer;
begin
Case (N > 0 ) Of True: J:=1; False: J := 2; End;
end;
Marco van de Voort
2006-03-05 11:07:09 UTC
Permalink
Post by J French
Post by Scott
if n > 0 then average := sum div n
else average := 0;
A very contrived example :-
Var
J, N :Integer;
begin
Case (N > 0 ) Of True: J:=1; False: J := 2; End;
end;
Simple and absolutely beautiful :-)

It even sucks as much in readability as the original C operator.
J French
2006-03-05 14:47:45 UTC
Permalink
On Sun, 5 Mar 2006 11:07:09 +0000 (UTC), Marco van de Voort
Post by Marco van de Voort
Post by J French
Post by Scott
if n > 0 then average := sum div n
else average := 0;
A very contrived example :-
Var
J, N :Integer;
begin
Case (N > 0 ) Of True: J:=1; False: J := 2; End;
end;
Simple and absolutely beautiful :-)
It even sucks as much in readability as the original C operator.
I cannot disagree - but it was irresistable ....
Arash Partow
2006-03-06 07:43:30 UTC
Permalink
That is a piece of true programming art.
beautiful indeed.



Arash Partow
Jamie
2006-03-05 18:05:14 UTC
Permalink
Post by Scott
Does Delphi have an operator similar to C's "?: ternary" operator?
Example: i := (n > 0) ? sum div n : 0
if n > 0 then average := sum div n
else average := 0;
the shortest i can break it down to is this.
if Boolean(n) then i := sum div n else i := 0;
--
Real Programmers Do things like this.
http://webpages.charter.net/jamie_5
Maarten Wiltink
2006-03-05 18:13:30 UTC
Permalink
Post by Jamie
Post by Scott
Does Delphi have an operator similar to C's "?: ternary" operator?
Example: i := (n > 0) ? sum div n : 0
if n > 0 then average := sum div n
else average := 0;
the shortest i can break it down to is this.
if Boolean(n) then i := sum div n else i := 0;
"n>0" is actually shorter than "Boolean(n)". Plus, you should really
cast to (probably) LongBool, gaining another letter.

Not even Jerry's beautifully twisted code can make it an _expression_ as
it is in C. It's still a statement, you can't pass it as a parameter.

Groetjes,
Maarten Wiltink
Hans-Peter Diettrich
2006-03-06 05:59:29 UTC
Permalink
Post by Maarten Wiltink
Not even Jerry's beautifully twisted code can make it an _expression_ as
it is in C. It's still a statement, you can't pass it as a parameter.
The statement can be wrapped into a (local) function:

function ternary: integer;
begin
if n > 0 then Result := sum div n else Result := 0;
end;

With more memory and runtime requirements, unless the compiler can
inline that function (FreePascal has inline functionality).

DoDi
Dunny
2006-03-05 23:04:09 UTC
Permalink
Post by Jamie
Post by Scott
Does Delphi have an operator similar to C's "?: ternary" operator?
Example: i := (n > 0) ? sum div n : 0
if n > 0 then average := sum div n
else average := 0;
the shortest i can break it down to is this.
if Boolean(n) then i := sum div n else i := 0;
Ooh!

I wonder if Delphi is as flexible as Sinclair BASIC...?

i := Integer(Boolean(n)) * (sum div n);

D.
Rob Kennedy
2006-03-05 23:54:36 UTC
Permalink
Post by Dunny
I wonder if Delphi is as flexible as Sinclair BASIC...?
i := Integer(Boolean(n)) * (sum div n);
That's more properly written as

i := Ord(n > 0) * sum div n

Type-casting n to Boolean chops off some bytes from n that might be
significant. Type-casting the Boolean to Integer makes assumptions about
the binary storage format of Boolean values.

The expression "n > 0" is guaranteed to be of type Boolean, so there's
no data loss. The Ord function is defined to return zero for False, and
one for True.

There's a problem, though. If n = 0, then all these Delphi examples will
crash with an EDivByZero exception. The corresponding C code will not;
C's conditional operator only evaluates two of its operands, never all
three.
--
Rob
Dunny
2006-03-05 23:58:00 UTC
Permalink
Post by Rob Kennedy
That's more properly written as
i := Ord(n > 0) * sum div n
Hmm. Yes, that's far neater.
Post by Rob Kennedy
Type-casting n to Boolean chops off some bytes from n that might be
significant. Type-casting the Boolean to Integer makes assumptions
about the binary storage format of Boolean values.
Ok, I can understand that... A negative integer cast as a DWord is huge,
after all. Wouldn't want to lose the high byte there.
Post by Rob Kennedy
There's a problem, though. If n = 0, then all these Delphi examples
will crash with an EDivByZero exception. The corresponding C code
will not; C's conditional operator only evaluates two of its
operands, never all three.
Yep, I realised that almost as soon as I'd posted it. Besides, I don't think
I'd use code like that - Delphi's compiler doesn't half make a mess of it,
and the compare from using IF is almost certainly faster.

D.
Jamie
2006-03-06 03:41:25 UTC
Permalink
Post by Dunny
Post by Jamie
Post by Scott
Does Delphi have an operator similar to C's "?: ternary" operator?
Example: i := (n > 0) ? sum div n : 0
if n > 0 then average := sum div n
else average := 0;
the shortest i can break it down to is this.
if Boolean(n) then i := sum div n else i := 0;
Ooh!
I wonder if Delphi is as flexible as Sinclair BASIC...?
i := Integer(Boolean(n)) * (sum div n);
D.
delphi does not automaticly generate a value of 1 if the
casted boolean is not 0! it only decides if the value is
0 or not 0!.. how ever, when ever delphi needs to create
a boolean from an operation it will then use 0 or 1.
in the above i don't think it will even compile.
--
Real Programmers Do things like this.
http://webpages.charter.net/jamie_5
Dunny
2006-03-06 18:55:54 UTC
Permalink
Post by Jamie
Post by Dunny
I wonder if Delphi is as flexible as Sinclair BASIC...?
i := Integer(Boolean(n)) * (sum div n);
delphi does not automaticly generate a value of 1 if the
casted boolean is not 0! it only decides if the value is
0 or not 0!.. how ever, when ever delphi needs to create
a boolean from an operation it will then use 0 or 1.
Yep - Boolean(25) results in a 1. Boolean(0) results in a 0.
Post by Jamie
in the above i don't think it will even compile.
It does, I tested it in Delphi 5. However, a neater solution was posted by
Rob using the Ord() function, but the example above would crash with
DivByZero if n = 0 - a trap I saw just after I hit Send...

/me recalls the heady days of

10 LET X=X+(INKEY$="P")-(INKEY$="O")

:-)

D.
Maarten Wiltink
2006-03-07 09:04:41 UTC
Permalink
"Dunny" <***@ntlworld.com> wrote in message news:_A%Of.77262$***@newsfe7-win.ntli.net...
[...]
Post by Dunny
/me recalls the heady days of
10 LET X=X+(INKEY$="P")-(INKEY$="O")
You can still do that, although Pascal insists on an Ord() here and
there. The rest is merely different syntax.

Is INKEY$ a synchronous function in your dialect, too?

Groetjes,
Maarten Wiltink
Dunny
2006-03-07 16:00:57 UTC
Permalink
Post by Maarten Wiltink
[...]
Post by Dunny
/me recalls the heady days of
10 LET X=X+(INKEY$="P")-(INKEY$="O")
You can still do that, although Pascal insists on an Ord() here and
there. The rest is merely different syntax.
Is INKEY$ a synchronous function in your dialect, too?
Pretty much. There's a 50hz interrupt which invokes an RST $38 instruction -
and at that address there's a routine that scans the keyboard ports via IN
instructions. The currently pressed key is stored in a system variable
(LAST_K).

When INKEY$ is called, it returns the ascii character of the key held down,
or a null string.

D.
Maarten Wiltink
2006-03-07 21:05:27 UTC
Permalink
Post by Dunny
Post by Maarten Wiltink
Post by Dunny
10 LET X=X+(INKEY$="P")-(INKEY$="O")
Is INKEY$ a synchronous function in your dialect, too?
[...]
Post by Dunny
When INKEY$ is called, it returns the ascii character of the key
held down, or a null string.
Not, then. Where I lived, INKEY$ waited for a key to be pressed.
You can no doubt imagine the face I made when seeing that code.

Groetjes,
Maarten Wiltink
Dunny
2006-03-07 22:02:37 UTC
Permalink
Post by Dunny
10 LET X=X+(INKEY$="P")-(INKEY$="O")
Not [INKEY$ is synchronous], then. Where I lived, INKEY$ waited for a key
to be pressed.
You can no doubt imagine the face I made when seeing that code.
I can just imagine :-)

What flavour of BASIC did you grow up with? Actually, I can't think what
sense that statement would make if it did wait for a key.

I remember learning that little trick when I was about 9 years old, and
thinking "good god, that's just so amazing..."

Because hey, it was - it was the shortest, quickest method of controlling a
moving character I could find in that language.

D.
Maarten Wiltink
2006-03-09 08:34:33 UTC
Permalink
Post by Dunny
Post by Dunny
10 LET X=X+(INKEY$="P")-(INKEY$="O")
Not [INKEY$ is synchronous], then. Where I lived, INKEY$ waited for
a key to be pressed.
[...]
Post by Dunny
What flavour of BASIC did you grow up with?
Who said it was Basic? It was Comal-80, which was very much like Basic
but with procedures and functions. However, we were _not_ allowed to
say that. Basic was a four-letter word. Bloody awful students'
introduction to computing.
Post by Dunny
Actually, I can't think what sense that statement would make if it
did wait for a key.
My point exactly.

Groetjes,
Maarten Wiltink
J French
2006-03-08 07:44:55 UTC
Permalink
On Tue, 7 Mar 2006 22:05:27 +0100, "Maarten Wiltink"
<***@kittensandcats.net> wrote:

<snip>
Post by Maarten Wiltink
Not, then. Where I lived, INKEY$ waited for a key to be pressed.
You can no doubt imagine the face I made when seeing that code.
You are thinking about Input$(1)

InKey$ 'peeks and grabs'

Sh*tty code though, in DOS BASIC you just don't create unnecessary
strings - it shafts memory.
Dunny
2006-03-08 18:38:35 UTC
Permalink
Post by J French
On Tue, 7 Mar 2006 22:05:27 +0100, "Maarten Wiltink"
<snip>
Post by Maarten Wiltink
Not, then. Where I lived, INKEY$ waited for a key to be pressed.
You can no doubt imagine the face I made when seeing that code.
You are thinking about Input$(1)
InKey$ 'peeks and grabs'
Sh*tty code though, in DOS BASIC you just don't create unnecessary
strings - it shafts memory.
This wasn't DOS BASIC - this was running on a Z80, and had very, very good
garbage collection code.

D.
J French
2006-03-09 09:31:47 UTC
Permalink
On Wed, 08 Mar 2006 18:38:35 GMT, "Dunny" <***@ntlworld.com>
wrote:

<snip>
Post by Dunny
Post by J French
Post by Maarten Wiltink
Not, then. Where I lived, INKEY$ waited for a key to be pressed.
You can no doubt imagine the face I made when seeing that code.
You are thinking about Input$(1)
InKey$ 'peeks and grabs'
Sh*tty code though, in DOS BASIC you just don't create unnecessary
strings - it shafts memory.
This wasn't DOS BASIC - this was running on a Z80, and had very, very good
garbage collection code.
Interesting, I used Commodore, Apple and CP/M, but never the Z80

One MS BASIC App I worked on had a load of 'pig ASM' for the keyboard
input to avoid creating strings
- the joke was LSet S$ = Input$(1) did exactly the same

Hans-Peter Diettrich
2006-03-06 06:04:30 UTC
Permalink
Post by Dunny
I wonder if Delphi is as flexible as Sinclair BASIC...?
i := Integer(Boolean(n)) * (sum div n);
Somehting like this can be done, of course. But I suspect that even your
BASIC program will raise an error when n is zero - I cannot test this
just now, my Spectrum is currently out of reach.

DoDi
Dr John Stockton
2006-03-06 17:36:14 UTC
Permalink
JRS: In article <J7KOf.27331$***@newsfe2-win.ntli.net>, dated
Sun, 5 Mar 2006 23:04:09 remote, seen in news:comp.lang.pascal.delphi.mi
Post by Dunny
Post by Jamie
Post by Scott
Does Delphi have an operator similar to C's "?: ternary" operator?
Example: i := (n > 0) ? sum div n : 0
if n > 0 then average := sum div n
else average := 0;
the shortest i can break it down to is this.
if Boolean(n) then i := sum div n else i := 0;
Ooh!
I wonder if Delphi is as flexible as Sinclair BASIC...?
i := Integer(Boolean(n)) * (sum div n);
That will do as it should, which is not what was actually wanted.
Boolean() is a typecast to a byte-sized value, but it does not change
the bits of the byte. Integer will then expand the byte to dword size.
The combination is essentially a 'mod 255' operation, or 'and $FF'. The
line will round sum down to be a multiple of n (I'm assuming everything
is positive and in-range for its storage size).

Such a ternary operator would be useful; it amounts to the conditional
arithmetic expression of Algol, though it should not be limited to
arithmetic.

But in Delphi style it should be written as
Answer := if condition then this else that ;
where both this and that are expressions assignable to answer.

I don't see why there should be any great difficulty in compiling it,
with 'if condition then this else that' usable wherever an expression is
allowed', those who don't like it don't have to use it.
--
© John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Delphi 3 Turnpike 4 ©
<URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/&c., FAQqy topics & links;
<URL:http://www.bancoems.com/CompLangPascalDelphiMisc-MiniFAQ.htm> clpdmFAQ;
<URL:http://www.borland.com/newsgroups/guide.html> news:borland.* Guidelines
Bruce Roberts
2006-03-06 20:15:51 UTC
Permalink
Post by Dr John Stockton
I don't see why there should be any great difficulty in compiling it,
with 'if condition then this else that' usable wherever an expression is
allowed', those who don't like it don't have to use it.
I wouldn't want to suggest that there is a great deal of difficulty
compiling it, but it does add some real complexity to the grammar. My
recollection is that the current grammar only permits the Not reserved word
in Terms. The only place that Not can appear is in a Term.

Add If to the permissible Terms probably adds IfElse and overloads these
reserved words since they could then start a statement or start a Term. (It
does mean that some compiletime errors may not be caught at the same point
as now, although this is probably a negligable factor.) Given that Borland
has not shared an accurrate and complete grammar for Delphi, it is
difficult to judge the actual impact of such a change.
Marco van de Voort
2006-03-07 10:34:51 UTC
Permalink
Post by Dr John Stockton
Such a ternary operator would be useful;
If I see requests for extensions at FPC, I define "usefull" as something
that makes something possible that can be done otherwise, not something that
saves typing. As soon as one gets too many constructs for the same thing,
the resulting language will become baroque.

An exception to this is it really is a heavy used construct that makes
conversion simpler.

IMHO this construct doesn't reach the threshold. I don't think anybody could
make a sane argument to adding it to Delphi except "C has it".
J French
2006-03-07 11:08:46 UTC
Permalink
On Tue, 7 Mar 2006 10:34:51 +0000 (UTC), Marco van de Voort
Post by Marco van de Voort
Post by Dr John Stockton
Such a ternary operator would be useful;
If I see requests for extensions at FPC, I define "usefull" as something
that makes something possible that can be done otherwise, not something that
saves typing. As soon as one gets too many constructs for the same thing,
the resulting language will become baroque.
An exception to this is it really is a heavy used construct that makes
conversion simpler.
IMHO this construct doesn't reach the threshold. I don't think anybody could
make a sane argument to adding it to Delphi except "C has it".
Which is probably a good reason for not adding it ...
Bruce Roberts
2006-03-06 15:48:57 UTC
Permalink
Post by Scott
Does Delphi have an operator similar to C's "?: ternary" operator?
No. The closest one can come are the IfThen functions but they are not
directly equivalent since all parameters must be fully evaluated. Hence
short-circuit boolean expression evaluation does not occur.

Any other workaround, nice as it may be, suffers from the fact that it
typically uses If or Case. In Delphi these are statements and statements do
not have results, unlike C statements (which are really expressions).

As nice as ? can be, it is one of those language elements that is open to
gross misuse. When I first learned C, I loved using them. Once I had to
maintain code I realized rather quickly that ? should be used sparingly and
not as a replacement for If or Case.
J French
2006-03-07 11:07:35 UTC
Permalink
Post by Scott
Does Delphi have an operator similar to C's "?: ternary" operator?
Example: i := (n > 0) ? sum div n : 0
if n > 0 then average := sum div n
else average := 0;
Just for a laugh :-

Average := Sum Div Max( 1, N )

Assuming Sum is zero if N is zero (which is pretty likely) it should
work.

Of course Max() is just a Function buried in Math.pas

One could produce ones own far more explicit Function
- I would opt for :-

Average := DivSafe( Sum, N )

That's not really so dumb, as checking for zero is not really a major
part of the routine - just an irritating niggle in the code.
Nicholas Sherlock
2006-03-07 21:34:32 UTC
Permalink
Post by J French
Average := DivSafe( Sum, N )
That's not really so dumb, as checking for zero is not really a major
part of the routine - just an irritating niggle in the code.
IMHO, it is a major part of the routine. As /0 is undefined, you must
make a decision about what value your average function will return. If
you always just DivSafe'd, without thinking about the value which will
be returned on fail, you may find calculations going wrong later on in
your code.

Cheers,
Nicholas Sherlock
J French
2006-03-08 07:55:47 UTC
Permalink
On Wed, 08 Mar 2006 10:34:32 +1300, Nicholas Sherlock
Post by Nicholas Sherlock
Post by J French
Average := DivSafe( Sum, N )
That's not really so dumb, as checking for zero is not really a major
part of the routine - just an irritating niggle in the code.
IMHO, it is a major part of the routine. As /0 is undefined, you must
make a decision about what value your average function will return. If
you always just DivSafe'd, without thinking about the value which will
be returned on fail, you may find calculations going wrong later on in
your code.
We differ on that point

- one day you may agree with me .. perhaps not

Since you are normally pretty canny, I reckon that you don't 'smell'
what the type of App the OP is producing.
Nicholas Sherlock
2006-03-08 09:16:06 UTC
Permalink
Post by J French
We differ on that point
- one day you may agree with me .. perhaps not
Maybe someday I will! :)
Post by J French
Since you are normally pretty canny, I reckon that you don't 'smell'
what the type of App the OP is producing.
What type of app is that..?

Cheers,
Nicholas Sherlock
J French
2006-03-09 07:59:16 UTC
Permalink
On Wed, 08 Mar 2006 22:16:06 +1300, Nicholas Sherlock
Post by Nicholas Sherlock
Post by J French
We differ on that point
- one day you may agree with me .. perhaps not
Maybe someday I will! :)
Post by J French
Since you are normally pretty canny, I reckon that you don't 'smell'
what the type of App the OP is producing.
What type of app is that..?
Looks like crunching through a whole load of Averages
- probably producing a report
- at a guess some sort of marking system
Loading...