# Lexical scope vs. Dynamic scope

**URL:** https://discourse.julialang.org/t/lexical-scope-vs-dynamic-scope/78829
**Category:** Internals & Design
**Created:** [March 31, 2022, 5:26pm UTC](https://discourse.julialang.org/t/lexical-scope-vs-dynamic-scope/78829 "2022-03-31T17:26:23Z")
**Posts on this page:** 9
**Page:** 2

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [April 1, 2022, 3:59pm UTC](https://discourse.julialang.org/t/lexical-scope-vs-dynamic-scope/78829/21 "2022-04-01T15:59:09Z")

</div>

We definitely can’t do it at this point, but it would be interesting for a future language to semantically guarantee that the value of a global will only be read and written to once by a function. (i.e. it captures the value on first use and writes to the value on last use).

---

<div class="post-metadata">

### Author: ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)
#### Post date: [April 1, 2022, 4:09pm UTC](https://discourse.julialang.org/t/lexical-scope-vs-dynamic-scope/78829/22 "2022-04-01T16:09:07Z")

</div>

I don’t see the point in making this a semantic guarantee, but since a read from a global is monotonic, this is already a valid optimization. Right now, it’s mostly just a matter of enabling LLVM to better reason about this.

---

<div class="post-metadata">

### Author: ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)
#### Post date: [April 1, 2022, 5:00pm UTC](https://discourse.julialang.org/t/lexical-scope-vs-dynamic-scope/78829/23 "2022-04-01T17:00:25Z")

</div>

It may be semantically valid in terms of memory models but if someone expects changes to globals to be immediately visible then this would be very surprising behavior. They could write code like this:

```julia
STOP::Bool = false

function main()
    while !STOP
        do_stuff()
    end
    global STOP = false
    return
end

function do_stuff()
    print(".")
    global STOP = rand() < 1e-3
end

main()

```

Is this bad code? Indubitably. But people would be pretty confused if `main()` never terminated.

---

<div class="post-metadata">

### Author: ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)
#### Post date: [April 1, 2022, 5:47pm UTC](https://discourse.julialang.org/t/lexical-scope-vs-dynamic-scope/78829/24 "2022-04-01T17:47:47Z")

</div>

Yeah, this optimization would not be valid if the function `do_stuff` isn’t inlined. You can still run into concurrency bugs very similar to this when using multiple threads though, which is why you can actually specify the atomic ordering for reading from a global in 1.9 (see [https://github.com/JuliaLang/julia/pull/44231](https://github.com/JuliaLang/julia/pull/44231)).

---

<div class="post-metadata">

### Author: ![Mark\_Nahabedian](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mark_nahabedian/32/16562_2.png) [@Mark\_Nahabedian](https://discourse.julialang.org/u/Mark_Nahabedian)
#### Post date: [April 7, 2022, 8:04pm UTC](https://discourse.julialang.org/t/lexical-scope-vs-dynamic-scope/78829/25 "2022-04-07T20:04:29Z")

</div>

The topic of this thread is Lexical Scope versus Dynamic Scope.

Indeed, code that is lexically scoped is much easier to understand, easier to reason about, and more efficient to execute.

Dynamic Scope does have it’s place though. Once every few years I find myself missing it. It is obvious when others need it too. The typical hack to work around the absence of dynamic scoping is for a library to introduce a “context” object which must be passed in by user code, passed around by all functions of that library, and passed to any user code that the library must call back to. One such example is

> **[context package - context - Go Packages](https://pkg.go.dev/context)**
>
> Package context defines the Context type, which carries deadlines, cancellation signals, and other request-scoped values across API boundaries and between processes.

but I think I have also seen this hack used in Julia libraries as well.

Suppose there is some library that your program needs to call in to, and that library will then call some inner part of your program. Now suppose the outer part of your program needs to communicate some piece of data to the inner part of your program and that piece of data is irrelevant to the library. Without dynamic scoping (or a kludgy implementation of it) there is no way to communicate that data in a thread safe manner.

---

<div class="post-metadata">

### Author: ![Zach\_Christensen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zach_christensen/32/7220_2.png) [@Zach\_Christensen](https://discourse.julialang.org/u/Zach_Christensen)
#### Post date: [April 8, 2022, 5:26pm UTC](https://discourse.julialang.org/t/lexical-scope-vs-dynamic-scope/78829/26 "2022-04-08T17:26:47Z")

</div>

In case anyone’s interested other programs that mess with variable scoping, [R does this](http://adv-r.had.co.nz/Environments.html). Having something conceptually similar may be useful for metaprogramming across function boundaries, but like most things in R it’s pretty messy and doesn’t translate well into something that could be easily type stable for writing simple code.

---

<div class="post-metadata">

### Author: ![c42f](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/c42f/32/52842_2.png) [@c42f](https://discourse.julialang.org/u/c42f)
#### Post date: [April 27, 2022, 1:15am UTC](https://discourse.julialang.org/t/lexical-scope-vs-dynamic-scope/78829/27 "2022-04-27T01:15:00Z")

</div>

Yes, dynamic scope has its place as a “better global”. We do have `Base.task_local_storage()`, though that comes with some caveats. There’s a package and PR prototyping an improved version here:

- [https://github.com/tkf/ContextVariablesX.jl](https://github.com/tkf/ContextVariablesX.jl)
- [https://github.com/JuliaLang/julia/pull/35833](https://github.com/JuliaLang/julia/pull/35833)

---

<div class="post-metadata">

### Author: ![amb007](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/amb007/32/6444_2.png) [@amb007](https://discourse.julialang.org/u/amb007)
#### Post date: [June 7, 2022, 10:07am UTC](https://discourse.julialang.org/t/lexical-scope-vs-dynamic-scope/78829/28 "2022-06-07T10:07:36Z")

</div>

This post was temporarily hidden by the community for possibly being off-topic, unfocused, inappropriate, or spammy.

---

<div class="post-metadata">

### Author: ![Leon\_Niceday](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/leon_niceday/32/216710_2.png) [@Leon\_Niceday](https://discourse.julialang.org/u/Leon_Niceday)
#### Post date: [May 14, 2025, 11:13pm UTC](https://discourse.julialang.org/t/lexical-scope-vs-dynamic-scope/78829/29 "2025-05-14T23:13:59Z")

</div>

[Scilab](https://en.wikipedia.org/wiki/Scilab) (1990) is a language with dynamic scope.  
[https://www.scilab.org/sites/default/files/progscilab-v.0.10\_en.pdf](https://www.scilab.org/sites/default/files/progscilab-v.0.10_en.pdf), section 4.5.3

[Previous page](https://discourse.julialang.org/t/lexical-scope-vs-dynamic-scope/78829.md?page=1)
