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

Reply via email to