Skip to content

Consider renaming ScopedValue to ContextValue #53644

Closed
@CameronBieganek

Description

@CameronBieganek

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:

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]:1

Example 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]:1

Discussion

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 2

Of 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions