On Nov 4, 2019, at 00:58, Soni L. <fakedme...@gmail.com> wrote:
> 
> That was meant to be NYI (Not Yet Implemented), sorry. (feel free to treat 
> "NIY" as "Not Implemented Yet" :P)

Ah. I use NotImplementedError for that, because there are unit testing 
frameworks that know how to count that differently from other unexpected 
exceptions—although it can be a problem when what you haven’t finished is an 
override for an abstract method (so it’s serving a double meaning), that 
doesn’t come up very often. 

> It seems useful to me to have the local declared but not defined, because you 
> haven't got around to implementing what it calls/etc, but you still know what 
> to do with it. I generally tend to just `foo = None`, but then you run the 
> risk of that code path actually getting silently taken and messing up program 
> state. Then you spend hours debugging what went wrong only to find out what 
> happened.

I usually raise NotImplementedError at the very top of the function, because 
it’s most visible there, and serves as enough of a signal that I don’t need to 
also add a #TODO comment.

And then, I do something like this further down:

    foo = figure_out_how_to_calculate_from(spam, eggs)

Then I don’t need foo = None with a comment saying to figure out how to 
calculate it from spam and eggs, because the (compiling but not running) code 
already says that.

And if I later think I’ve finished the function and remove the 
NotImplementedError incorrectly, I’ll get a NameError instead of possibly 
incorrect values from None.

If I needed to test some but not all of the behavior of a partially-written 
function, I suppose raising in the middle might be helpful. But usually I 
refactor out the parts I know how to write early when they’re significant 
enough to be worth testing. But anyway, I appreciate that not everyone works 
the same way I do, so I can see why you might find foo = raise more useful than 
me. In particular, if you don’t refactor the function into smaller bits, the 
raise presumably shows exactly how far you’ve gotten and which part isn’t done 
yet.

> In Rust, for example, one can do `let foo = unimplemented!();`.

I actually use this in Rust, but then Rust is pretty different. If you name 
something figure_out_how_to_calculate without defining it anywhere, you get a 
compile error rather than a runtime error. You can’t do operations that are 
guaranteed to be illegal even in code that’s guaranteed not to run. Figuring 
out the types (which aren’t being inferred for you in half-written code) is 
sometimes half the work of writing the code. Also, at least for me, bad habits 
imported from other languages mean I often don’t refactor functions as much 
(even when it’s easy to prove that the call and moves will get inlined and 
optimized out, because it’s not easy in C++ I don’t instinctively go there). So 
for me, that doesn’t transfer into wanting to do the same thing in Python. But 
again, I can see how for others it might.

Anyway, I’m +/-0 on a raise_expr that’s maximally restricted in the way I 
described, -0 on the same thing but with a rule allowing it to be used on the 
right side of an assignment (just like yield_expr, so it should be no problem 
to implement), -0.5 on making it a general expression instead of a heavily 
restricted one, -1 on making it a magic function (or anything else that’s not 
backward compatible) instead of syntax, and -0.5 on leaving it as a statement 
but adding throw to the stdlib somewhere.

_______________________________________________
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/T6V3OCWOMLRVEALPLTXDE6RV32LIQYRE/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to