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