-
-
Notifications
You must be signed in to change notification settings - Fork 102
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
Scope context #376
Comments
One way we could do this would be to take advantage of the inherited nature of the Instead, it might be wiser to attach ancestry information to scopes, probably as part of the metatable. This can be as simple as a reference to the outer scope. Interested code can then associate scopes with contextual values, and walk up the ancestry to learn about contextual values defined in ancestors. |
Storing ancestry information also has the potential to significantly improve lifetime analysis, by allowing analysis to flow up to common ancestors rather than having to flow down from the scopes being analysed. |
Proposed user facing API surface:
The returned |
Alternatively, it'd be possible to ship a design that weakly maps the current scope to a value, but this is undesirable because it forces the developer to explicitly introduce scopes where they want the value to be independent. By creating the scope when a value is changed, we can create that breakpoint automatically. |
As a further consideration, For this purpose, we could introduce a new Alternatively, we could introduce some kind of object that, when constructed in a scope, can read the Contextual, but this is heavier memory-wise and probably overengineered. |
The mechanisms for We might want to force one or the other to be used per-contextual. It's weird to want to mix them. Alternatively, call-stack-based contextuals could be removed outright. |
One year on from the original introduction of scopes as a concept, they've single-handedly come to dominate how Fusion thinks about memory management. The reason is simple; it allows developers to define the behaviour of a whole block of code at once, with clean and explicit ways of inserting sub-blocks or isolated islands, and perpendicular ways of inheriting behaviour across those boundaries.
There's another problem for which this is useful: contextual cascading values.
In an ideal world, cascading values act identically to prop drilling: with lexical scope. This is very, very hard to do in practice - without some constraints, the problem is impossible to generally solve in Luau.
So right now, contextuals use an approximation - a call-stack-based approach - by exposing a value only for the duration of a callback. This works so long as the receiving code isn't re-entered once the callback returns - when that happens, the temporary value will have been erased by then. Additionally, other values might leak through if the contextual is set for the code causing the re-entry.
Scopes are actually a great candidate for replacing this. Scopes are "lexical-ish" because they are explicitly drilled down through components, though they're not guaranteed to be unique for each lexical scope. However, this nuance doesn't matter, because the only time scopes have to be distinct from each other is when a distinct observable effect is wanted; either a different lifetime or a different
__index
table.The concept of contextual values fits neatly into this model: the observable effect is the value the contextual takes on, which is represented by a distinct scope in which the contextual has a different value.
To make this work, we will need to decide on some mechanism to inherit data into derived and inner scopes, and should consider renaming
scoped
to more clearly be a detached 'starting point' or 'root'.The text was updated successfully, but these errors were encountered: