Let's get to the fundamental problem with this. It is DWIM magic, and you haven't (as far as I have seen) yet specified how we are supposed to use it or predict how it is supposed to work.
Here is your syntax again: > > def a_potentially_recursive_function(some, args) with > > ExceptionWeCareAbout: > > some.user_code() > > code_we_assume_is_safe() > > if args.something and some_condition: > > raise ExceptionWeCareAbout # Line (A) > > > > How does the compiler know that *only* ExceptionWeCareAbout originating > > in Line (A) should be re-raised, and any other location turned into > > RuntimeError? > > Same way Rust decides whether to propagate or unwrap a Result: you > *must* tell the compiler. How do I tell the compiler? There is no sign in your syntax that Line (A) is special or different from the rest of the lines in the function. > > What if I factor out those last two lines and make it: > > > > def a_potentially_recursive_function(some, args) with > > ExceptionWeCareAbout: > > some.user_code() > > code_we_assume_is_safe() > > check_condition_or_raise(args.something, some_condition) > > > > How does the compiler decide to re-raise exceptions originating in the > > last line but not the first two? > > In this case, it explicitly doesn't. So by refactoring a conditional raise (if condition: raise) into a function, I completely change the meaning of the code? That's just great. Not. > You explicitly told it the last line doesn't raise any exceptions that > contribute to your API's exception surface. I did? I wasn't aware that I told the interpeter *explicitly* anything about the last line. How does this work? That's what I'm trying to understand about your proposal: I write a function, and stick "with ExceptionName" into the function declaration line: def function(some, args) with ExceptionWeCareAbout: and then write a block of code under that declaration, and *somehow* in some completely unspecified way the compiler Does What I Mean by deciding that *some* of those lines which raise ExceptionWeCareAbout it should let the exception through while *other* lines that raise the same exception should be guarded against ExceptionWeCareAbout and have them raise RuntimeError instead. And I have no idea how it decides which lines are guarded and which are not. You tell me that I explicitly instructed the compiler which lines should be guarded, but I don't know how I did it. > You *must* use try: check_condition_or_raise(args.something, > some_condition) except ExceptionWeCareAbout: raise But that's not what the pre-refactoring code had. All I did was move: # The original version, before refactoring. if args.something and some_condition: raise ExceptionWeCareAbout into a named function and call that. In the original code, I didn't have to explicitly catch the exception and then immediately re-raise it: # This was never used. try: if args.something and some_condition: raise ExceptionWeCareAbout except ExceptionWeCareAbout: raise But now you are telling me that if I move the `if... raise` lines into a function I have to also wrap it in a try...except, catch the exception, and immediately and unconditionally re-raise it. This behaviour may be clear to *you* but I cannot read your mind. Unless you actually tell me how the compiler knows which part of the block need to be guarded and which parts don't, I have no clue how this is happening except "the compiler magically infers what I want it to do". -- Steve _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/AZYPCANN4N7G2IIE6SL6ONUBKBHCVR3G/ Code of Conduct: http://python.org/psf/codeofconduct/