[Python-ideas] if expensive_computation() as x:

spir denis.spir at gmail.com
Fri Feb 14 09:24:12 CET 2014


On 02/14/2014 09:05 AM, spir wrote:
> On 02/13/2014 10:59 PM, Ram Rachum wrote:
>> Hi everybody,
>>
>> Please excuse the recent torrent of crazy ideas :)
>>
>> I was reading code of the Shpaml project, trying to make a patch, while I
>> saw code that looked inelegant to me. I considered how to improve it, but
>> then saw I don't know how to.
>>
>> The code paraphrased is this:
>>
>>      if expensive_computation_0():
>>          x = expensive_computation_0()
>>          # Do something with x...
>>      elif expensive_computation_1():
>>          x = expensive_computation_1()
>>          # Do something with x...
>>      elif expensive_computation_2():
>>          x = expensive_computation_2()
>>          # Do something with x...
>
> Such a pattern is rather common, eg in some kind of hand-baked parsing. (Say you
> have match funcs returning False if no match, True if match but you don't
> want/need the result, some "form" having a truth value of True if you need the
> form; then you are matching a pattern choice).
>
> Solution 0: for a little and particular choice:
>
>      x = expensive_computation_0()
>      if not x:
>          x = expensive_computation_1()
>      if not x:
>          x = expensive_computation_2()
>      # assert(x)   # or whatever check
>
> Alternative:
>      x = expensive_computation_0() \
>      or expensive_computation_1() \
>      or expensive_computation_2()
>      # assert(x)
>
> Works due to lazy evaluation of logical operations.
>
>
> Solution 1: for a big choice, or the general case:
>
>      for comp in computations:
>          x = comp()
>          if x: break
>      # assert(x)
>
>

Oh, I did not get the action performed is supposed to be different in each case. 
(Note: you should have used indices 1, 2, 3... for actions as well.) Then, we 
need a // array of actions. Something like:

    for i in range(len(comps)):	# or zip
         x = comps[i]()
         if x:
             actions[i]()
             break
    # assert(x)

But it still assumes all computations and all actions take the same input. Else, 
we're left with unrolling the loop: but how to break outside no loop? The 
solution may be to export the whole series comps/actions into a func and return 
from it.

     def f ():
         ...
         g()
         ...

     def g ():
         x = comp1()
         if x:
             action1(x)
             return
         x = comp2()
         if x:
             action2(x)
             return
         ...

d



More information about the Python-ideas mailing list