[Python-ideas] And now for something completely different

Terry Reedy tjreedy at udel.edu
Thu Sep 18 05:54:18 CEST 2008

Cliff Wells wrote:
> You can accomplish this to some degree by using lambda, 

You can do it completely as far as I know.

 > but I'd much  prefer something indicated in the function signature
 > than in the calling code.

Given Python's nature as a compiled dynamic language, indications are 
really needed in both caller and callee, as at present: pass a function 
and call it.  Without an explicit indication at the call site, the 
compiler would have to compile both direct evaluation and function 
object creation and the code to select between them at runtime according 
to an attribute of the function resulting from evaluation of the 
presumed function expression.  This would slow *all* function calls, 
which are slow enough already.  Also, one could not tell what objects 
get passed to a function without knowing the signature in detail, making 
code harder to read.

There is already a way to be flexible without magical arg object 
switching and with only exceptional need for del/lambda.

def iff(cond, if_result, else_result):
   if cond:
     if hasattr(if_result, '__call__'): return if_result()
     else: return if_result
     if hasattr(else_result, '__call__'): return else_result()
     else: return else_result

for i in [0,1,2]:
   print("I gave you %s gold piece%s." % (i,iff(i==1, '', 's'))) #3.0

#prints (imagine a typical RPG game)
I gave you 0 gold pieces.
I gave you 1 gold piece.
I gave you 2 gold pieces.

One only needs the wrapper if the object to be returned is a function
   example -- iff(cond, lambda: math.sin, lambda: math.cos)(x)
or if the expression needs to be guarded by the condition because it 
would otherwise be invalid (iff(x, lambda x=x: sin(x)/x, 1) -- this 
might work without the default arg, but might have scope problems)
or if it would take a long time.

But many conditional values are constant or quick to evaluate and the 
short-circuiting is not needed.  Many of the exceptions might better be 
defined in functions anyway.

def sin_or_cos(cond,x):
   if cond: return math.sin(x)
   else: return math.cos(x)

def sin_over_x(x):
   if x: return math.sin(x)/x
   else: return 0

Terry J. Reedy

More information about the Python-ideas mailing list