What does "surprising behaviors" in the documentation of ITensor mean?

In this page it is said that

The reason we recommend the let...end block is that code written in the Julia global scope can have some surprising behaviors. Putting your code into a let block avoids these issues.

What does this mean? Are there any examples?

Hi, so here is an example of the type I was thinking of when I wrote that. Consider the following code:

function increase(n::Int)
  return n+m
end

n = 5
m = 2

r = increase(n)
@show r

This code runs and outputs the number 7 as expected. However, when you look more closely at the code inside the function increase, you will see that the variable m there is not a variable that got passed into the function’s list of arguments. Yet the code still runs, because m is defined in global scope so the function can still access it.

It may not look like a problem for this simple code, but in more complicated codes when using certain variable naming conventions, so that the same variable name could appear more than once, across different functions, one could end up with surprising situations where there is global state across different functions.

Hope that helps. Similarly, in past versions of Julia, for loops would give strange results in global scope because of the special properties of global scope, however, in more recent versions of Julia that situation has been improved.

Miles

3 Likes

Note that this advice isn’t specific to ITensor.jl. If you care about performance, avoid global scope. If you don’t care about performance, still avoid global scope: put meaningful blocks of code into functions, and make them self-contained to avoid “spurious action at distance”.

IMO, global scope is really only useful for interactivity and playing around. In this case, I neither care about performance nor “style”.

(let ... end introduces a local scope, so does function funcname() ... end)

4 Likes