-
Notifications
You must be signed in to change notification settings - Fork 72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prevent accidental proc overwriting, proc signature overloads #1213
Comments
I'm not even sure what the current behavior is, so I'm not sure what would be best :) |
Current behavior is that the last definition takes precedent. proc _a() {
msg("First definition");
}
proc _a() {
msg("Second definition");
}
_a(); // Second Definition |
Well currently there's no way of knowing what files run first, so having a final tag could potentially have use but... Because of the way it currently works, I don't think anyone would be careless enough to define the same proc twice, I know I sure wouldn't. That uncertainty currently keeps us in kind of a rigid structure. Consider how Java and C# work where you not only have to match the name of a method but the number and type of variables in order to trigger a specific override of a method. MethodScript doesn't have that so if a proc is updated to require more/fewer/different arguments, you have to go change that throughout your code. Final won't solve that problem because instead of selectively updating different parts of code that use it, it just forces one version to essentially override any other version. Maybe instead of final you could implement something like overloads or a version system, something like ver=1.3 which would be used unless a higher version of the proc is found elsewhere. That way at least if we were able to distribute zipped packages it would be easier, as we could just include all our procs with each package and still ensure that whomever is using them has the latest version. What real use case is there for final? |
The lack of file order only matters for auto_includes. There is never a use for proc overriding there, so it can always be detected and have a warning. (ie. all procs in auto_includes should be treated as final) |
Again, what real use case is there for final? |
The same use case as the |
If procs in auto_includes are non-supported and throw a warning, then there's no reason why two _add procs should ever be a problem. Three possibilities:
Final keywords in Java/C# exist because overriding is something you might actually want to do. Say you install a package you don't want to mess with, but you want to add properties or override a particular method. One good example of this is importing Microsoft's Identity packages which handle user logins and OAuth. It comes with a class for a user, but maybe you want to add a property for the user's associated Minecraft account or something. You can override the constructor to get that information on account creation for instance. The reason that is useful is because classes are big huge things with many parts. Procs are just code snippets, it's pretty much all or nothing in terms of modifying. No reason to intentionally override a proc means no reason to lock it down either. |
proc _a() {
// default
}
if(@asdf) {
proc _a() {
// new behavior
}
} Of course, in this case, this is intentional, but in the second proposal, this currently valid code would require changes (albeit simple ones). But in any case, it seems like you're arguing against both proposals, rather than for one or the other. In both proposals, there is now a way to have final procs, it's just whether that's the default or not, and which keywords are used to make the procs be final. |
To be clear, I use proc overriding in a few projects. It is useful. It is current behavior. (there could be instances in people's scripts where a file is included twice) There's just no good reason to override an auto_included proc that I can think of. It probably shouldn't be in an auto_include if one were overriding it. |
In my example #1, I think that's a compelling use case, but that's within the same file. But you could just as easily break that into a separate file with no issues. Also, the functionality wouldn't be removed, that option isn't on the table at all. The question is whether or not to make it so that it's the default or requires a keyword. |
Also couldn't...
|
Not necessarily. Consider the case where it logically makes sense to define it in different files, perhaps if you're replicating like a stubbing system. |
A discussion came up about being able to overwrite procs. There are definitely good use cases for being able to overwrite procs, but the discussion was that perhaps this is not a good thing by default/generally.
A number of proposals were offered, summarized here. For clarity, the term "final" is taken to mean that a proc cannot be overwritten, whether or not there is a keyword
final
involved.final
is introduced, and when applied to procs, prevents them from being overwritten elsewhere.overwrites
and/oroverwritable
are allowed to be overwritten.For option 2, there is still a need to determine the specific keywords that are used. Do you put the
overwritable
keyword on the "master" proc, and theoverwrites
keyword on the sub-proc? Or do you just have a single keywordoverwrite
which you tag on all procs that are intended on being overwritten and the procs that overwrite them? This is a minor discussion that needs to happen still, but does not materially change the overall decision.Another discussion is to also perform signature matching on non-final procs. So redefining a proc (which is either implicitly or explicitly overwritable) with a new signature should be disallowed. I generally support this, but this is a different decision and implementation. This may however prevent valid use case, so further user research needs to be done to provide input to this decision.
The text was updated successfully, but these errors were encountered: