Proposal: function which simulates C ?: operator

A

Adal Chiriliuc

I think a function similar to the one below should be added to the
builtin module:

def boolselect(condition, trueresult, falseresult):
if condition:
return trueresult
else:
return falseresult

--- WITH

scalewidth = boolselect(self.__vertical, _scalew, _scaleh)

a1 = 0
a4 = boolselect(self.__vertical, self.__width, self.__height)
a2 = (a4 - scalewidth) // 2
a3 = a2 + scalewidth

self.__meterwidth = self.__meterrect[0].Width()
self.__meterheight = self.__meterrect[0].Height()
self.__meterlength = boolselect(self.__vertical, self.__meterheight, self.__meterwidth)

t = boolselect(self.__range >= 18, -18, -12)
redzone = self.__dBToOffset(-6)
yellowzone = self.__dBToOffset(t)

--- WITHOUT

if self.__vertical:
scalewidth = _scalew
else:
scalewidth = _scaleh

a1 = 0
if self.__vertical:
a4 = self.__width
else:
a4 = self.__height
a2 = (a4 - scalewidth) // 2
a3 = a2 + scalewidth

self.__meterwidth = self.__meterrect[0].Width()
self.__meterheight = self.__meterrect[0].Height()
if self.__vertical:
self.__meterlength = self.__meterheight
else:
self.__meterlength = self.__meterwidth

if self.__range >= 18:
t = -18
else:
t = -12
redzone = self.__dBToOffset(-6)
yellowzone = self.__dBToOffset(t)
 
M

Mel Wilson

I think a function similar to the one below should be added to the
builtin module:

def boolselect(condition, trueresult, falseresult):
if condition:
return trueresult
else:
return falseresult

[ ... ]
What do you think?

PS: maybe a better name than boolselect could be found.

Some poeple might be disturbed by what it would do with

this_line = boolselect (dummy_flag, "Dummy line\n", infile.readline())

Side-effects are the main reason that a simple function
can't generally replace a full conditional ternary operator.
See google for the ternary operator debate, and see the other
discussion in clp right now.

Regards. Mel.
 
M

Mitja

Adal Chiriliuc said:
I think a function similar to the one below should be
added to the
builtin module:

def boolselect(condition, trueresult, falseresult):
if condition:
return trueresult
else:
return falseresult

--- WITH

scalewidth = boolselect(self.__vertical, _scalew, _scaleh)

--- WITHOUT

if self.__vertical:
scalewidth = _scalew
else:
scalewidth = _scaleh
What do you think?

Here's a nifty workaround I figured out myself but am sure others use it as
well:
scalewidth=(_scaleh,_scalew)[__self.vertical]

HTH

It's not as readable as the "if cond ? true_expr : false_expr", but I think
introducing syntax like this is far from needed and pretty complicated.
 
P

Paul Rubin

Adal Chiriliuc said:
I think a function similar to the one below should be added to the
builtin module:

def boolselect(condition, trueresult, falseresult):
if condition:
return trueresult
else:
return falseresult

That doesn't work because both results get evaluated either way. E.g.

boolselect(x==0, f(x), g(x))

calls both f and g. You need something like

(lambda: g(x), lambda: f(x))[bool(condition)]()
 
E

Erik Max Francis

Adal said:
I think a function similar to the one below should be added to the
builtin module:

def boolselect(condition, trueresult, falseresult):
if condition:
return trueresult
else:
return falseresult

This doesn't simulate the conditional operator; it doesn't do
short-circuiting. See PEP 308; this kind of construct was explicitly
rejected (but then, so is the whole PEP).
 
T

Tor Iver Wilhelmsen

Paul Rubin said:
(lambda: g(x), lambda: f(x))[bool(condition)]()

Since you call the object afterwards, you don't need the lambdas
(which add a layer of indirection), just the function references:

(g, f)[bool(condition)]()
 
E

Erik Max Francis

Tor said:
Paul Rubin said:
(lambda: g(x), lambda: f(x))[bool(condition)]()

Since you call the object afterwards, you don't need the lambdas
(which add a layer of indirection), just the function references:

(g, f)[bool(condition)]()

Well, you meant:

(g, f)[bool(condition)](x)

but that was taking his example too literally; he was just using f(x)
and g(x) to expressions that you wanted laziy evaluated.
 
P

Paul Rubin

Tor Iver Wilhelmsen said:
(lambda: g(x), lambda: f(x))[bool(condition)]()

Since you call the object afterwards, you don't need the lambdas
(which add a layer of indirection), just the function references:

(g, f)[bool(condition)]()

Good catch, for that particular example. The lambdas are needed for
more general cases, e.g. (x > 0 ? (f(x)+g(y)) : (h(x)-z(y)))

There's been various proposals floated for macros in Python. If
something like that becomes real, that can solve this whole problem.
 
A

Adal Chiriliuc

I didn't know this was discussed so much in the past. I should have
searched before.

Most of you objected that this is a bad solution because it evaluates
both variants. That's true if you want a real ternary operator. I now
think I gave a bad title to this thread. It shouldn't have mentioned
?:

I've searched through the C++ sources I'm now porting to Python
(450 KB) and found 44 uses of ?: and from these only 4 needed short
circuit evaluation (to avoid dereferencing NULL pointers or zero
division).

I now suggest that this function be added without implying that it's
the Python equivalent of ?: and with the docs clearly explaining that
it's not ?: and how it differs. It will be like Python private vars,
almost but not quite (of course, Python private vars are a lot more
close to the ideal than this is).

Anyway, I suggested this because the function I have is actually named
Util.BoolSelect, and this is kind of long :)
 
P

Peter Hansen

Adal said:
I didn't know this was discussed so much in the past. I should have
searched before.

And if you read all of it, you probably wouldn't be making
the following suggestion, either. :)
I now suggest that this function be added without implying that it's
the Python equivalent of ?: and with the docs clearly explaining that
it's not ?: and how it differs.

It won't happen because (a) it's a trivial function to write
on-demand, and (b) there are already several different ways of
spelling it with current Python syntax if you don't want a
function, and (c) I suspect that the requirement for short-circuit
evaluation would actually be *more* common in Python than it
appears it is in C++ based on your very limited sample population.

-Peter
 
D

Dan Bishop

Mitja said:
Adal Chiriliuc said:
I think a function similar to the one below should be
added to the
builtin module:

def boolselect(condition, trueresult, falseresult):
if condition:
return trueresult
else:
return falseresult

--- WITH

scalewidth = boolselect(self.__vertical, _scalew, _scaleh)

--- WITHOUT

if self.__vertical:
scalewidth = _scalew
else:
scalewidth = _scaleh
What do you think?

Here's a nifty workaround I figured out myself but am sure others use it as
well:
scalewidth=(_scaleh,_scalew)[__self.vertical]

If you're going to use the "(F, T)[C]" syntax, it would be better to
write it as "(F, T)[bool(C)]" to ensure that the array index is 0 or
1.

However, a better alternative is "(C and [T] or [F])[0]", which
short-circuits and also has the advantage of having the same order as
"if".

If you're absolutely certain that T will never be false, you can
simplify this to "C and T or F".
 
E

Erik Max Francis

Dan said:
However, a better alternative is "(C and [T] or [F])[0]", which
short-circuits and also has the advantage of having the same order as
"if".

It's got the same order, but it's completely opaque. It's hardly better
if you're interested in readability.
 
R

Reinhold Birkenfeld

Peter said:
And if you read all of it, you probably wouldn't be making
the following suggestion, either. :)


It won't happen because (a) it's a trivial function to write
on-demand,

How do you write this function without lambda in the call?
and (b) there are already several different ways of
spelling it with current Python syntax if you don't want a
function

One uglier than the other.
and (c) I suspect that the requirement for short-circuit
evaluation would actually be *more* common in Python than it
appears it is in C++ based on your very limited sample population.

ACK.

Reinhold
 
P

Peter Hansen

Reinhold said:
How do you write this function without lambda in the call?

Basically, you use if/then like you are "supposed" to. :)
But the OP wasn't asking about a short-circuit version, just
the trivial fully evaluated function approach.
One uglier than the other.

Agreed. Use if/then and save the sanity of your maintenance
programmers.

Ironic that Bill the Cat changed the meaning of that from
positive to negative. :) (Or did he always use mixed-case,
so that all-caps ACK is still uniquely ASCII?)

-Peter
 
R

Reinhold Birkenfeld

Peter said:
Basically, you use if/then like you are "supposed" to. :)
But the OP wasn't asking about a short-circuit version, just
the trivial fully evaluated function approach.

Granted. This or (x and y or z) without y being false...
Agreed. Use if/then and save the sanity of your maintenance
programmers.


Ironic that Bill the Cat changed the meaning of that from
positive to negative. :) (Or did he always use mixed-case,
so that all-caps ACK is still uniquely ASCII?)

Well, I don't know Bill the Cat, should I?

Reinhold
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,565
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top