Invoking return through a function?

Christian Gollwitzer auriocus at gmx.de
Mon Oct 30 03:47:15 EDT 2017


Am 30.10.17 um 01:42 schrieb Steve D'Aprano:
> On Mon, 30 Oct 2017 03:35 am, Alberto Riva wrote:
>> And as Bartc
>> pointed out, we already have this situation with exceptions, so it would
>> be nothing new.
> 
> Pardon me, but it was *me* who pointed out the analogy with exceptions, not
> Bart. But this is different from an exception.
> 
> The similarity is quite weak:
> 
> - any function can raise an exception;
> 
> - your hoped for feature would allow any function to cause the
>    caller to return;

For another data point, I'm regularly using another language, which does 
have this feature without macros - Tcl. In Tcl, you can return a control 
code alongside with the value which causes the caller to /return/, throw 
an /error/ or execute a /break/ or /continue/ statement. It is realised 
by additional options to "return"; translated into Python syntax it 
would look like:

	return ("somevalue", code=return)

The caller can still intercept this return code using "catch".
This feature can be used to implement one's own control structures, but 
it is rarely used in other contexts. It is there for completeness; in 
order to allow functions to be written which mimic exactly break, 
continue, error (="raise" in Python) and return. In practice, the only 
situation where it is regularly used is argument checking. Consider:

def root(X):
	if X < 0:
		return("X must be positive", code=error)

root(-1)

With "raise" instead of "return", the stack trace points to the line 
containing "raise", but the actual error is at the call site. With 
"return code=error" the stack trace ends at the invocation of "root", 
where the real error is, and thus "root" would behave more like 
math.sqrt(), where you also don't get a stack trace pointing to the line 
of C code which throws the error.

>> Indeed, what I'm asking for could be accomplished by
>> wrapping the body of each function in a try/catch block for an ad-hoc
>> exception type.
> 
> A terrible idea. Why not just write a "validate input" function that checks
> your input and returns True for valid and False for invalid, then:
> 
>      if not valid(args):
>          return
 >
 > That's little harder to type than
 >
 >      returnIfNotValid(args)
 >
 > and much more comprehensible.
 >


Indeed, that is way better for this use case. The OP really wants to 
abuse that feature. For statistics, I ran a few greps over the entire 
tcllib:

return               16309
return -code error    2271
return -code continue   54
return -code break       7
return -code return     56

Returning an "error" is prevalent, which is mostly used for the case 
described above. Returning "break", "continue" and "return" is used in 
the guts of some parsing engines and in tricky control structures, but 
otherwise very rare. It is also used in Tk code to interrupt a series of 
bindings, and therefore also in Tkinter code (where the string "break" 
is returned)

> 
>> But again, since the language doesn't have macros
> 
> And this is the sort of misfeature why Guido is dead-set against Python ever
> getting them.
> 
> Yes, we get it that Lisp macros are really, really powerful. But there are two
> bottle-necks in coding:
> 
> - writing the code in the first place;
> 
> - maintaining the code afterwards.
> 
> Macros are aimed at simplifying the first, at the cost of the second. That's
> not a strategy Python follows.

Abusus non tollit usum. Python already has a macro-esque feature, namely 
decorators. "But everyone can write a decorator which does magic things 
and hide it under an @blabla...." - yes they can, but on the other hands 
they allow such wonderful things as asyncio, properties or the numba jit 
compiler. It is never a good argument to say "there is no feature X, 
because GvR is such a god that he knew the feature isn't needed, and 
see? we are doing well without it!". Unfortunately, that logical fallacy 
is heard quite often in this group.

	Christian




More information about the Python-list mailing list