A recurring problem I've seen a lot since the addition of local methods - and in particular in async
optimizations (and not just me) is that it is very easy to accidentally introduce shared state into a local function when you really didn't want to. For example:
void Foo(int a) {
void Bar(int val) {
Blah(a); // <== error; this was meant to be val
}
// ...
Bar(a);
}
This is a common intent when using local functions to enclose a method, without actually intending to allow shared capture state.
Currently, the only "fix" here is to move the method out:
static void Bar(int val) {
Blah(val); // <== fixed, because the compiler told us about it
}
void Foo(int a) {
// ...
Bar(a);
}
This works, but it pollutes the space and loses code locality and expressiveness. I actually find myself routinely copy/pasting local methods out and back in again to check that they still compile - to see if I've leaked state.
Proposal: allow the static
modifier on local functions, to express the intent to divorce all state. I'm not 100% sure that static
is the right word, but it seems close. The effect would be simply to enforce that variables (parameters and locals) declared outside the static
local method are not in scope inside the local method, essentially as though the local method had been declared outside the method. The "local method", then, is simply here for code cleanliness reasons.
This has the effect of avoiding unintended captured state machinery.
Example:
void Foo(int a) {
static void Bar(int val) {
Blah(val); // <== fixed, because the compiler told us about it
}
// ...
Bar(a);
}
There is an outstanding question of whether it is acceptable to share the this
instance but nothing else; this ambiguity is perhaps the biggest thing against the static
keyword.
Additional possibility: because of the lack of state, it allows re-use of the most obvious/correct variable names. I've seen lots of examples essentially like:
void Foo(int a) {
void Bar(int innerA) {
Blah(innerA); // <== note awkward naming
}
// ...
Bar(a);
}
but this proposal allows the "obvious" names to be used consistently:
void Foo(int a) {
static void Bar(int a) {
Blah(a);
}
// ...
Bar(a);
}
Drawaes, Joe4evr, iam3yal, benaadams, DavidArno and 42 morejnm2, MattDillard, federicoce-moravia, vasiliuk, DrSensor and 2 moreNeme12AustinBryan
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4