On Tue, 05 Jan 2010 02:31:34 +0000, r0g wrote: > A pattern I have used a few times is that of returning an explicit > success/failure code alongside whatever the function normally returns.
That doesn't work for languages that can only return a single result, e.g. C or Pascal. You can fake it by creating a struct that contains a flag and the result you want, but that means doubling the number of data types you deal with. > While subsequent programmers might not intuit the need to test for > (implicit) "magic" return values they ought to notice if they start > getting tuples back where they expected scalars... What if they're expecting tuples as the result? > def foo(x) > if x>0: > return True, x*x > else: > return False, "Bad value of x in foo:",str(x) > > ok, value = foo(-1) Oops, that gives: ValueError: too many values to unpack because you've returned three items instead of two. When an idiom is easy to get wrong, it's time to think hard about it. > if ok: > print "foo of x is", value > else: > print "ERROR:", value Whenever I come across a function that returns a flag and a result, I never know whether the flag comes first or second. Should I write: flag, result = foo(x) or result, flag = foo(x) I've seen APIs that do both. And I never know if the flag should be interpreted as a success or a failure. Should I write: ok, result = foo(x) if ok: process(result) else: fail() or err, result = foo(x) if err: fail() else: process(result) Again, I've seen APIs that do both. And if the flag indicates failure, what should go into result? An error code? An error message? That's impossible for statically-typed languages, unless they have variant records or the function normally returns a string. And even if you dismiss all those concerns, it still hurts readability by obfuscating the code. Consider somebody who wants to do this: result = foo(bar(x)) but instead has to do this: flag, result = bar(x) if flag: # I think this means success flag, result = foo(x) # oops, I meant result Again, it's error-prone and messy. Imagine writing: flag, a = sin(x) if flag: flag, b = sqrt(x) if flag: flag, c = cos(b) if flag: flag, d = exp(a + c) if flag: flag, e = log(x) if flag: # Finally, the result we want!!! flag, y = d/e if not flag: fail(y) else: fail(e) else: fail(d) else: fail(c) else: fail(b) else: fail(a) Compare that to the way with exceptions: y = exp(sin(x) + cos(sqrt(x)))/log(x) Which would you prefer? -- Steven -- http://mail.python.org/mailman/listinfo/python-list