The manual's section on variable scope sucks

You make a valid point — some users just want to skim the chapter to find a solution to a particular problem. However, now the chapter is full of well-meaning additions and side points like this which makes it hard to read. I think that a concise edit would be better.

Your example runs fine for me, I must be missing something.

Thank you, I must be more precise with the wording — assignment makes use of enclosing (local) scopes.

1 Like

I don’t think that going into implementation details would be useful here. The user should have a mental model.

Thanks, I should be wording it more precisely (assignment when there is no existing variable in [local] scope).

Technically the = in

let x = ...
    ...
end

is not assignment, it is the syntax of let that happens to be using the same syntax as assignment (just like = in for x = 1:3 is not assignment).

Maybe. The problem I am running into is terminology: I think I should introduce concepts (block, local, global, enclosing, outer, inner, etc) then illustrate with examples.

Thank you all for replies, I will keep working on this. At some point I will fill this up with code and put it in a repo that you can comment on.

4 Likes

Maybe we can split the documentation into two parts: explanations and how-to guides.
(ref: Diátaxis (diataxis.fr))

We define and explain what “variable scope” is in the manual.

Then we could add a new “How-to” parts where we teach the user how to fix various errors related to variable scopes.

1 Like

Another source of language confusion is the use of “variable” at all. Using “labels” and “values” is probably clearer.

However, I admit that the necessity of sticking with a precise language in the manual restricts, a lot, it’s accessibility. That’s why I like opinionated blog posts.

Agreed; eliminate them if you can. I’d prefer a rewrite where complexity is added as you go down the page, so a user can read as far as they are comfortable. A user should not need to understand every nuanced scope detail to run their first loop.

It runs fine in a let block or some other local scope, where the output is

0
10

But if the outer scope is global, I get one of the following:

0
0
0
...
10
10
10
...
ERROR: LoadError: UndefVarError: `i` not defined in local scope
Suggestion: check for an assignment to a local variable that shadows a global of the same name.

I emphasize the while case because I think this is where users are most likely to encounter their first scoping problem. I wrote loops like this all the time without thinking about it in Matlab.

@sadish-d’s main complaint seems to be that the scope manual is imprecise. My main complaint is that the scope manual is unapproachable. These are somewhat competing design philosophies. In a perfect world you would achieve both simultaneously, but you may need to focus different sections one way or another.

That said, I feel strongly both can co-exist in the same manual. My personal preference would be to switch the manual organization from:

# Topic A
if global
  if script
    rules
  end
  if interactive
    rules
  end
else
  rules
end

# Topic B
if ...

to

# Usually
## Explaination
Julia users are encouraged to write code inside functions where the following scoping rules apply.
## Topic A
rules
## Topic B
rules

# Scoping Changes for Global Variables
## Explaination
global variables behave differently because ... (across files, compiler performance)
## Topic A
rule changes
## Topic B
rule changes

# Scoping Changes for Interactive Sessions
## Explaination
the REPL and notebooks behave differently because ... (convenience trumps performance)
## Topic A
rule changes
## Topic B
rule changes

I think this gives you the best shot of being precise and accessible simultaneously.

1 Like

@lmiq and @Nathan_Boyer have brought up a point that I also struggled with. The whole manual actually reads like an “opinionated blog post”. There are aspects of this that I appreciate. For instance, the section on scope mentions the motivation behind having the soft scope behavior in the REPL. I am glad I came across this information because I can now appreciate the reasoning behind it; without it, I might have thought that this is a strange design choice. However, I don’t think the manual is the right place for it.

I think of the manual as an authoritative source of information on how the language functions. I think blog posts or forums are a fine place to learn about the philosophy and history of the language.

If we write a simplisitic and uncomprehensive manual to make it accessible to absolute beginners, it will be of little use to users who are advanced enough that they’re running into important corner cases. Without a definitive language reference for these users, I can not see how Julia as a language can be seen as mature. If advanced users have to rely on luck/visibility and the generosity of the community to fix issues they run into, Julia cannot be considered a mature language. The unreliability of documentation is one reason I, as of today, do not recommend Julia for “serious work”.

1 Like

AFAIK the manual chapter on scope is not unreliable or incorrect, it just needs some editing because of historical accretion. In fact, I think it is extremely well written in some parts.

Let’s not get carried away: while understanding scope is important, if you are an experienced programmer who does Serious Work:tm: you already program in a way that it is very unlikely that you run into problems with scope in Julia, because experienced programmers organize their code into functions from the start.

The paradox here is that inexperienced users (mostly scientist, writing scripts with control flow, moving code from functions to the REPL and back, etc) run into the weird nuances and corner cases of scope.

14 Likes