- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 5.7k
Description
Introduction
The new ScopedValue feature is really nice, but I think the name and the description of the feature in terms of dynamic scope is likely to lead to confusion.
There was a claim on Discourse that the PR had "an extensive analysis and bikeshedding of the naming". However, I have read through the entire PR and I disagree with that statement. There is some discussion of the name, but it is not a very complete discussion. In particular, it is surprising that there was no discussion regarding using the terminology "context" instead of "dynamic scope". In PR #35833, @tkf pointed out that the "context" terminology is used in at least four major programming languages:
- Python: contextvars
- .NET: ExecutionContext
- Kotlin: CoroutineContext
- Go: Context
Julia is a lexically scoped language, and the Scoped Values PR does not change that. Below are a couple examples that I think emphasize that what ScopedValue provides is not dynamic scoping.
(Disclaimer: I have only tested these using ScopedValues.jl. I need to install juliaup so I can get nightly.)
Example 1
julia> using ScopedValues
julia> f() = a[];
julia> function g()
           a = ScopedValue(1)
           f()
       end;
julia> g()
ERROR: UndefVarError: `a` not defined
Stacktrace:
 [1] f()
   @ Main ./REPL[2]:1
 [2] g()
   @ Main ./REPL[3]:3
 [3] top-level scope
   @ REPL[4]:1Example 2
julia> module A
           f() = a[]
           export f
       end
Main.A
julia> module B
           using ScopedValues
           using ..A
           a = ScopedValue(1)
           g() = f()
           export g
       end
Main.B
julia> using .B
julia> g()
ERROR: UndefVarError: `a` not defined
Stacktrace:
 [1] f()
   @ Main.A ./REPL[1]:2
 [2] g()
   @ Main.B ./REPL[2]:5
 [3] top-level scope
   @ REPL[4]:1Discussion
Both of these examples would work if ScopedValue provided true dynamic scoping. So essentially we are telling the user that Julia uses a subtle combination of lexical scoping and dynamic scoping. I think that's more confusing than it needs to be. We should describe this feature as a "context" feature rather than a "dynamic scoping" feature. This is about more than just the name, it is about our semantic understanding of what the feature provides.
So, after a renaming, this feature could look like this:
f() = a[]
a = ContextValue(1)
newcontext(a => 2) do
    f()
end # returns 2Of course the precise naming is up for debate. Possible names for the context entering function:
- with
- withcontext
- context
- incontext
- updatecontext
- newcontext
I think updatecontext and newcontext are probably the most accurate names to describe what they do.