|Problems? Is your data what you think it is?|
Re^7: ref to read-only alias ... why? (eval)by tye (Cardinal)
|on Jan 06, 2012 at 22:34 UTC||Need Help??|
We showed that any call-by-reference can be affected.
That's an overstatement. The only thing that can be impacted is a sub that tries to modify an alias and then gets passed a read-only value and where that situation isn't just declared a bug and gets fixed. So, yes, exactly as I said, the worst possible case can be solved by adding a simple eval around the code that modifies the reference but is (badly) designed to also tolerate the failure in the case of read-only parameters.
but this must at least be documented
So the standard Perl documentation absolutely must document that trying to modify an alias to a read-only scalar might fail if you try to modify it? Or is your point that it is imperative to document that it might not fail? The first case seems completely reasonable to expect from the existing documentation. The latter is quite an edge case and seems not particularly vital to document, especially since I predict that you'll have plenty of fun just getting such a documentation patch approved since you'll probably just trigger a protracted (or another abandoned) argument over whether the inconsistency is a real bug or not.
UPDATE: And how do you expect eval to help if there is no error thrown?
If no error is ever thrown, then nobody knows and nobody cares and there is nothing to fix. The expressed problem was that there was no error thrown one place but then an error was thrown someplace else. Once the problem is found, fix the problem. It is easy to fix such a problem (at least in a relatively stupid manner, i.e. eval). It is better to fix it by declaring it a bug where the constant got passed to a sub that was designed to modify its argument. Even better is to stop writing subs that modify their argument thanks to implicit aliasing instead of requiring a reference to the thing-to-be-modified to be passed in explicitly.
Not only does changethis( \1 ) make the mistake much easier to spot, it also will cause such things to always fail. And this isn't the only reason to avoid modification via implicit alias. I'm not saying such should absolutely never, ever be used. But, yes, I've seen plenty of problems with it. It is, indeed, more fragile than being explicit. And given that somebody went and used this only-aluded-to sub in a way where a constant got passed to it, I strongly suspect that the interface to this sub is worse than just your average "modify one of your arguments" cases.
Yes, it is nice when Perl can catch potential errors for you. But there are certainly limits to that. But I'll probably address that more directly in a separate reply.
I don't see how mention of this in the documentation would have even been much help in this situation. The odds of such documentation being noticed and then causing the potential problem to be noticed before stuff was shipped seems miniscule to me. As for "helping people desperately trying to understand the reason why", I don't see how it could help in that case, either. It would only help after the source of the problem has already been well identified and then it only helps in allowing those involved to more quickly (we hope) accept that such is a subtle interaction and is not an out-right Perl bug (and I'm not convinced it would actually do that in this case anyway).
If you want to avoid frustrating debugging, then I suggest that you stop doing fragile things. That's the main reason I avoid a lot of things that I've found to be more fragile than others over the years. But I suspect if you'd posted some of this code and I'd responded "You may not want to do that", that you would not have been quick to follow my advice (based on some prior conversations). Now you know some of the pain that I've felt over the years that has lead me to program in a "conservative" style. It is obviously still your choice. But this is exactly the kind of pain I try to avoid and sometimes try to help other people to avoid.
I also don't use Data::Alias. Just FYI.