@@ -17,18 +17,15 @@ concurrently.
1717 Scoped values were introduced in Julia 1.11. In Julia 1.8+ a compatible
1818 implementation is available from the package ScopedValues.jl.
1919
20- In its simplest form you can create a [ ` Base.ScopedValue ` ] ( @ref ) with a
21- default value and then use [ ` Base.with ` ] (@ref with) or [ ` Base.@with ` ] ( @ref ) to
22- enter a new dynamic scope.
20+ In its simplest form you can create a [ ` ScopedValue ` ] (@ref Base.ScopedValues.ScopedValue)
21+ with a default value and then use [ ` with ` ] (@ref Base.ScopedValues.with) or
22+ [ ` @with ` ] (@ref Base.ScopedValues.@with ) to enter a new dynamic scope. The new scope will
23+ inherit all values from the parent scope (and recursively from all outer scopes) with the
24+ provided scoped value taking priority over previous definitions.
2325
24- The new scope will inherit all values from the parent scope
25- (and recursively from all outer scopes) with the provided scoped
26- value taking priority over previous definitions.
27-
28- Let's first look at an example of ** lexical** scope:
29-
30- A ` let ` statements begins a new lexical scope within which the outer definition
31- of ` x ` is shadowed by it's inner definition.
26+ Let's first look at an example of ** lexical** scope. A ` let ` statement begins
27+ a new lexical scope within which the outer definition of ` x ` is shadowed by
28+ it's inner definition.
3229
3330``` julia
3431x = 1
3835@show x # 1
3936```
4037
41- Since Julia uses lexical scope the variable ` x ` is bound within the function ` f `
42- to the global scope and entering a ` let ` scope does not change the value ` f `
43- observes.
38+ In the following example, since Julia uses lexical scope, the variable ` x ` in the body
39+ of ` f ` refers to the ` x ` defined in the global scope, and entering a ` let ` scope does
40+ not change the value ` f ` observes.
4441
4542``` julia
4643x = 1
6461f () # 1
6562```
6663
67- Not that the observed value of the ` ScopedValue ` is dependent on the execution
64+ Note that the observed value of the ` ScopedValue ` is dependent on the execution
6865path of the program.
6966
7067It often makes sense to use a ` const ` variable to point to a scoped value,
@@ -74,34 +71,54 @@ and you can set the value of multiple `ScopedValue`s with one call to `with`.
7471``` julia
7572using Base. ScopedValues
7673
77- const scoped_val = ScopedValue (1 )
78- const scoped_val2 = ScopedValue (0 )
79-
80- # Enter a new dynamic scope and set value
81- @show scoped_val[] # 1
82- @show scoped_val2[] # 0
83- with (scoped_val => 2 ) do
84- @show scoped_val[] # 2
85- @show scoped_val2[] # 0
86- with (scoped_val => 3 , scoped_val2 => 5 ) do
87- @show scoped_val[] # 3
88- @show scoped_val2[] # 5
74+ f () = @show a[]
75+ g () = @show b[]
76+
77+ const a = ScopedValue (1 )
78+ const b = ScopedValue (2 )
79+
80+ f () # a[] = 1
81+ g () # b[] = 2
82+
83+ # Enter a new dynamic scope and set value.
84+ with (a => 3 ) do
85+ f () # a[] = 3
86+ g () # b[] = 2
87+ with (a => 4 , b => 5 ) do
88+ f () # a[] = 4
89+ g () # b[] = 5
8990 end
90- @show scoped_val [] # 2
91- @show scoped_val2 [] # 0
91+ f () # a [] = 3
92+ g () # b [] = 2
9293end
93- @show scoped_val[] # 1
94- @show scoped_val2[] # 0
94+
95+ f () # a[] = 1
96+ g () # b[] = 2
9597```
9698
97- Since ` with ` requires a closure or a function and creates another call-frame,
98- it can sometimes be beneficial to use the macro form.
99+ ` ScopedValues ` provides a macro version of ` with ` . The expression ` @with var=>val expr `
100+ evaluates ` expr ` in a new dynamic scope with ` var ` set to ` val ` . ` @with var=>val expr `
101+ is equivalent to ` with(var=>val) do expr end ` . However, ` with ` requires a zero-argument
102+ closure or function, which results in an extra call-frame. As an example, consider the
103+ following function ` f ` :
99104
100105``` julia
101106using Base. ScopedValues
107+ const a = ScopedValue (1 )
108+ f (x) = a[] + x
109+ ```
110+
111+ If you wish to run ` f ` in a dynamic scope with ` a ` set to ` 2 ` , then you can use ` with ` :
102112
103- const STATE = ScopedValue {State} ()
104- with_state (f, state:: State ) = @with (STATE => state, f ())
113+ ``` julia
114+ with (() -> f (10 ), a=> 2 )
115+ ```
116+
117+ However, this requires wrapping ` f ` in a zero-argument function. If you wish to avoid
118+ the extra call-frame, then you can use the ` @with ` macro:
119+
120+ ``` julia
121+ @with a=> 2 f (10 )
105122```
106123
107124!!! note
@@ -265,11 +282,11 @@ Base.@kwdef struct Configuration
265282 verbose:: Bool = false
266283end
267284
268- const CONFIG = ScopedValue (Configuration ())
285+ const CONFIG = ScopedValue (Configuration (color = true ))
269286
270- @with CONFIG => Configuration (CONFIG[], color = true ) begin
287+ @with CONFIG => Configuration (color = CONFIG[]. color, verbose = true ) begin
271288 @show CONFIG[]. color # true
272- @show CONFIG[]. verbose # false
289+ @show CONFIG[]. verbose # true
273290end
274291```
275292
0 commit comments