SoftGlobalScope is a package for the Julia language that simplifies the variable scoping rules for code in global scope. It is intended for interactive shells (the REPL, IJulia, etcetera) to make it easier to work interactively with Julia, especially for beginners.
In particular, SoftGlobalScope provides a function
softscope that can transform Julia code from using the default "hard" scoping rules to simpler "soft" scoping rules in global scope only.
In Julia 1.5, "soft scoping" became the default for the built-in Julia REPL, and the SoftGlobalScope module simply calls through to the standard-library
REPL.softscope function. The advantage of using the SoftGlobalScope library is that it also works with previous Julia versions.
Hard and soft global scopes
Starting in Julia 0.7, when you assign to global variables in the context of an inner scope (a
for loop or a
let statement) you need to explicitly declare the variable
global in order to distinguish it from declaring a new variable. We refer to this as "hard" scoping rules. For example, the following code gives an warning in 0.7:
julia> s = 0 0 julia> for i = 1:10 s = s + i end ┌ Warning: Deprecated syntax `implicit assignment to global variable `s``. └ Use `global s` instead.
and an error in Julia 1.0:
julia> s = 0 0 julia> for i = 1:10 s = s + i # wrong: defines a new local variable s end ERROR: UndefVarError: s not defined
To make it work in 1.0, you need a
julia> for i = 1:10 global s = s + i end julia> s # should be 1 + 2 + ⋯ + 10 = 55 55
This only applies to global variables; similar code inside a function (or whenever
s is a local variable) works fine without any added keyword:
julia> function f(n) s = 0 for i = 1:n s = s + i end return s end f (generic function with 1 method) julia> f(10) 55
However, for interactive use, especially for new users, the necessity of the
global keyword, and the difference between code in local and global scopes, can be confusing and was ultimately reverted. The SoftGlobalScope package exists to make it easier for interactive shells to automatically insert the
global keyword in common cases, what we term "soft" global scope.
SoftGlobalScope module exports two functions
softscope_include_string, and a macro
You can transform the expression using
softscope(module, expression) to automatically insert the necessary
global keyword. For example, assuming that the module
Main has a global variable
s (as above), you can do:
julia> softscope(Main, :(for i = 1:10 s += i end)) :(for i = 1:10 #= REPL:2 =# global s += i end)
You can then execute the statement with
eval. Alternatively, you can decorate the expression with the
julia> s = 0; julia> @softscope for i = 1:10 s += i end julia> s 55
This macro should only be used in the global scope (e.g., via the REPL); using this macro within a function is likely to lead to unintended consequences.
You can execute an entire sequence of statements using "soft" global scoping rules via
softscope_include_string(module, string, filename="string"):
julia> softscope_include_string(Main, """ s = 0 for i = 1:10 s += i end s """) 55
(This function works like
include_string, returning the value of the last evaluated expression.)
In Julia 0.6, no code transformations are required, so
softscope returns the original expression
softscope_include_string is equivalent to
include_string. In Julia 1.5,
softscope_include_string(m, x) is equivalent to
include_string(REPL.softscope, m, x) using the
softscope transformation function provided by Julia's
REPL standard library.