Re: Enhancing variable scope control

These objections -- such as they are -- are all applicable to every instance of "I wrote a function" or even "I named a variable" in any particular namespace: not just within imports, either. Anywhere. Global context. Sub functions. etc. Collisions, etc... not a big deal. Change a name. It'll still work the same. Nothing to it. No matter what the context is in Python. If you were talking about using a compiled library without the source code (and here come the back hats), depending on the linking and permissions, you could probably *still* change the name(s) in the library. But we're talking about an interpreted scripting language. We have the source code for everything. Or should. There is no mystery to be had. You want your own TestDottedQuad? You fear collisions? Fine. Write it as MyTest23DottedQuad87qxy or whatever. Be really random about it if it assuages your concerns. Or just rename your new instance, or the one extending the library (remember,it's an addition, if it's there, something added it. So you *can* change it if that's your call.) if you can't stand to write a new name for yours. Either way, bingo. Your functionality is present in your project. The other functionality is present as well. Both can be used with your strings. Choose. Enjoy your choice. You want to write it the hard way, as a loose function that can't handle class objects like strings? You can do that too. Something immutable is broken or not functional for your purposes? Lift the code, fix it, give it your own name, and use it. As an extension or directly. Whatever floats your boat. There. Done. Easily. Or... like these non-Python Ruby people that keep mysteriously polluting the argument - just tell the team "we're not going to do that." Again, problem solved. You do *not* have to cripple a language to resolve this in any particular direction. But wait.... you told them and they won't/can't comply? That's not a language issue. That's a "your team needs different staffing" issue. And mind you, this is all in the context of "big projects." Doing something yourself? Not even worth a handwave. Write what you need, test it, secure it, make it work, move on. There are myriad ways to get naming issues into compliance with whatever metric you want. Regardless of circumstance. This "we're going to save you from yourself" mentality serves to coddle weak and/or lazy programmers while crippling the rest. The entire idea that these naming issues (and that's all they are) cannot be coped with absolutely trivially is both nonsensical and insupportable. For instance: Obviously if you were to say "extend library with X", and X was already present (remember, these are immutable), such an attempt would fail. Bang. Exception. The very first time you tried it. Therefore, you're already directly on the path of "going to need a non-colliding name to use my particular function." See how easy that was? It's absurd to claim that this is any kind of meaningful obstacle. If it happens, you just fix it. Like any other programming issue. This is what we do. Are you thinking "but what if it wasn't tested so no one saw an exception?" In that case, again, we have a staffing issue. Not a language issue. As for the "big project" argument put forth earlier, that is also invalid. In any big project, if the devs aren't outright newbs anyway, people are given responsibility for specific functionality, and if random person X wants to mod existing function Y, they submit a suggestion, it goes through the appropriate process and gets accepted (possibly altered, such as... the name), or not. Pull requests, etc. Whatever the process is. But should there not be that (obvious and common these days) process, Any function in the project is subject to name collisions, any use of any library with name X / function X is subject to collisions, etc. And how do we get out of such things? if library A and library B have the same names, or prehaps function X and function Y, we change one of them. Now you have your multiple names and/or namespaces and/or names within namespaces. Likewise, if a function is added (at any level) and there is a name collision, we can change that too. We can notify our crew and say "globally edit 'TestDottedQuad' to 'MyTest23DottedQuad87qxy', and by the way, we're having subs for lunch." Trivial. If your crew isn't up for such things... well. That's a different problem entirely. I appreciate that you have strong feelings about this, but you (neither of the respondents here) have not presented any good arguments. Not even one. That doesn't mean there aren't supporters of your positions - of course there are - but every level of computing history is replete with bad ideas supported by many, and good ideas trampled on by just as many. Perceptrons/Minsky. Scrums. Clumsy typing systems. Chiclet keyboards. Freeform formatting. "Comment every line of code." Segment registers (and oh boy did that one cost us progress!) etc., etc., etc.
I concur...
Concurring with one another doesn't ensure that you're right. It may also mean you're both wrong in similar or identical ways. To reiterate: I've already implemented this functionality through the auspices of a preprocessor, which also means, no monkey patching. It works very well, does exactly what I wanted, and improved my particular circumstance significantly. And then we have:
I find that implausible.
Okay. However, since I know the truth of it, I'll proceed to not worry in the least that your thought process ended up there.

On Fri, 2 Dec 2022 at 21:49, Anony Mous <fyngyrz@gmail.com> wrote:
Or... like these non-Python Ruby people that keep mysteriously polluting the argument - just tell the team "we're not going to do that." Again, problem solved. You do *not* have to cripple a language to resolve this in any particular direction. But wait.... you told them and they won't/can't comply? That's not a language issue. That's a "your team needs different staffing" issue.
So if I understand you correctly, the argument is: 1) You want to add a feature that Ruby programmers have a lot of experience with. 2) People on this list who know Ruby tell you "that's a bad idea" 3) You say "That's okay, everyone can just not use the feature!" Seems to me this is a solved problem. Everyone can already just not use the feature! If you have any doubts as to the scale of the problem that Ruby's culture of monkeypatching leads to, check out this quiz: https://railshurts.com/frames/quiz/ As a non-Ruby programmer, my scores were pretty much equivalent to GUESSING. I was completely unable to distinguish Ruby (the core language) from features added by Rails (a web framework). That means, if I were writing some code in, say, a Jekyll plugin, I would have to check very carefully to figure out whether the monkeypatching had been made available or not. Effectively, this means that "Ruby code" and "Ruby code" can be two completely different things. Imagine if this code produces a floating-point value: x = 1 / 3 but this code produces a fractions.Fraction: import fractions x = 1 / 3 This is *insane* and a terrible idea. (Though I wouldn't be averse to something like "1f / 3" where you have a fraction literal. That's different, since the spelling makes it clear.)
You want to write it the hard way, as a loose function that can't handle class objects like strings?
What do you mean, "class objects"? Every object in Python has a type. But if you mean that this is the easy way: some_list.length() and this is the hard way: len(some_list) then I have some very disappointing news for you. Not everything has to be a method. ChrisA

On Fri, Dec 02, 2022 at 03:48:36AM -0700, Anony Mous wrote:
The fact that you can't tell the difference between **non-collisions** of names in different namespaces, and **actual collisions** of names in the same namespace, makes me sad. The idea that you have absolutely nothing to learn from the hard-won experience of other developers is why we have so much unmaintainable, bad code in the world :-(
coddle weak and/or lazy programmers while crippling the rest.
Oh, we have a Real Programmer™ here. http://www.catb.org/jargon/html/story-of-mel.html I'm glad that your Python pre-processor works for you. -- Steve

Anony Mous writes:
You can't always get what you want But if you try some time You might find You get what you need. Batteries included![tm] Jagger and Richards evidently knew a lot about language design. ;-)
It works very well, does exactly what I wanted, and improved my particular circumstance significantly.
Nobody is asking you to give it up. We're saying that based on our limited experience, and Ruby's much greater experience, we don't want it as a standard feature in the publicly shared Python language implemented by this project. Many of us program large systems in Python, and we've found that certain restrictive rules that can be a drag on individual programmers make it easier to work together on them. One of them is "no monkey patching", and it is accepted by consensus. Steve

On 2022-12-02 02:48, Anony Mous wrote:
It seems you still don't really grasp the scope (har har) of the problem here. Suppose there is library A and library B and your program uses both of them. Now you write your program to "extend A with X". You test it and everything else works fine. Now six months later a new version of *library B* decides to also "extend A with X". Now your program breaks, not because of any change in your code, nor in the code of the library you extended, but because of a change in the code of a separate library. You can't just "choose a non-colliding name", because by allowing this sort of monkeypatching you're breaking down the namespacing barriers between different modules. A name that's non-colliding *today* might collide down the road. The way things work now, this can still happen to some extent, but it's greatly mitigated by the fact that each library only has to worry about naming collisions within its own code. If libraries start going around creating names in other libraries willy-nilly, any library may potentially break any other library (and thus all code that depends on either). That would be a debugging nightmare. Of course, even so, this is still possible in current Python, because we *can* monkeypatch things. But it's a bad idea and most libraries don't do it; also, our ability to monkeypatch builtins is limited . It seems what you're describing is a system for encouraging more monkeypatching (including of builtins), which isn't a road I'd want to go down. -- Brendan Barnwell "Do not follow where the path may lead. Go, instead, where there is no path, and leave a trail." --author unknown

On Fri, 2 Dec 2022 at 21:49, Anony Mous <fyngyrz@gmail.com> wrote:
Or... like these non-Python Ruby people that keep mysteriously polluting the argument - just tell the team "we're not going to do that." Again, problem solved. You do *not* have to cripple a language to resolve this in any particular direction. But wait.... you told them and they won't/can't comply? That's not a language issue. That's a "your team needs different staffing" issue.
So if I understand you correctly, the argument is: 1) You want to add a feature that Ruby programmers have a lot of experience with. 2) People on this list who know Ruby tell you "that's a bad idea" 3) You say "That's okay, everyone can just not use the feature!" Seems to me this is a solved problem. Everyone can already just not use the feature! If you have any doubts as to the scale of the problem that Ruby's culture of monkeypatching leads to, check out this quiz: https://railshurts.com/frames/quiz/ As a non-Ruby programmer, my scores were pretty much equivalent to GUESSING. I was completely unable to distinguish Ruby (the core language) from features added by Rails (a web framework). That means, if I were writing some code in, say, a Jekyll plugin, I would have to check very carefully to figure out whether the monkeypatching had been made available or not. Effectively, this means that "Ruby code" and "Ruby code" can be two completely different things. Imagine if this code produces a floating-point value: x = 1 / 3 but this code produces a fractions.Fraction: import fractions x = 1 / 3 This is *insane* and a terrible idea. (Though I wouldn't be averse to something like "1f / 3" where you have a fraction literal. That's different, since the spelling makes it clear.)
You want to write it the hard way, as a loose function that can't handle class objects like strings?
What do you mean, "class objects"? Every object in Python has a type. But if you mean that this is the easy way: some_list.length() and this is the hard way: len(some_list) then I have some very disappointing news for you. Not everything has to be a method. ChrisA

On Fri, Dec 02, 2022 at 03:48:36AM -0700, Anony Mous wrote:
The fact that you can't tell the difference between **non-collisions** of names in different namespaces, and **actual collisions** of names in the same namespace, makes me sad. The idea that you have absolutely nothing to learn from the hard-won experience of other developers is why we have so much unmaintainable, bad code in the world :-(
coddle weak and/or lazy programmers while crippling the rest.
Oh, we have a Real Programmer™ here. http://www.catb.org/jargon/html/story-of-mel.html I'm glad that your Python pre-processor works for you. -- Steve

Anony Mous writes:
You can't always get what you want But if you try some time You might find You get what you need. Batteries included![tm] Jagger and Richards evidently knew a lot about language design. ;-)
It works very well, does exactly what I wanted, and improved my particular circumstance significantly.
Nobody is asking you to give it up. We're saying that based on our limited experience, and Ruby's much greater experience, we don't want it as a standard feature in the publicly shared Python language implemented by this project. Many of us program large systems in Python, and we've found that certain restrictive rules that can be a drag on individual programmers make it easier to work together on them. One of them is "no monkey patching", and it is accepted by consensus. Steve

On 2022-12-02 02:48, Anony Mous wrote:
It seems you still don't really grasp the scope (har har) of the problem here. Suppose there is library A and library B and your program uses both of them. Now you write your program to "extend A with X". You test it and everything else works fine. Now six months later a new version of *library B* decides to also "extend A with X". Now your program breaks, not because of any change in your code, nor in the code of the library you extended, but because of a change in the code of a separate library. You can't just "choose a non-colliding name", because by allowing this sort of monkeypatching you're breaking down the namespacing barriers between different modules. A name that's non-colliding *today* might collide down the road. The way things work now, this can still happen to some extent, but it's greatly mitigated by the fact that each library only has to worry about naming collisions within its own code. If libraries start going around creating names in other libraries willy-nilly, any library may potentially break any other library (and thus all code that depends on either). That would be a debugging nightmare. Of course, even so, this is still possible in current Python, because we *can* monkeypatch things. But it's a bad idea and most libraries don't do it; also, our ability to monkeypatch builtins is limited . It seems what you're describing is a system for encouraging more monkeypatching (including of builtins), which isn't a road I'd want to go down. -- Brendan Barnwell "Do not follow where the path may lead. Go, instead, where there is no path, and leave a trail." --author unknown
participants (5)
-
Anony Mous
-
Brendan Barnwell
-
Chris Angelico
-
Stephen J. Turnbull
-
Steven D'Aprano