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
--
https://mail.python.org/mailman/listinfo/python-list