-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Confusing documentation for scope rules. #40238
Comments
In other words, If an assignment to a variable occurs in a local scope and there is no variable with that name visible in that scope, then the variable is implicitly declared as a new local in that scope. This is always true. In all of your examples, there is an existing local that is visible from an outer scope, so the antecedent doesn't apply.
It doesn't matter which one, the rule applies either way: if Of course things like scope are tricky to understand from rules like this, which is why there are also examples in the rest of the section. In particular, you'll note that the |
Yes, I looked at the sum_to example as well after the discourse discussion; I agree that having an inner function would be more helpful. It doesn't matter which one, the rule applies either way: if x is a local variable in this scope, then that binding is updated; if it is an existing local in some containing local scope, then that outer binding is updated. It matters what Existing local refers to; because if it specifically refers to a variable within a particular scope, then the variable in the outer scope shouldn't get updated, and the second clause applies: Hard scope: If x is not already a local variable and assignment occurs inside of any hard scope construct (i.e. within a let block, function or macro body, comprehension, or generator), a new local named x is created in the scope of the assignment I would rephrase the initial paragraph to the following: A new local scope is introduced by most code blocks (see above table for a complete list). Some programming languages require explicitly declaring new variables before using them. Explicit declaration works in Julia too: in any local scope, writing Hard scope: If x is not already a local variable in the current or any outer scope, and assignment occurs inside of any hard scope construct (i.e. within a let block, function or macro body, comprehension, or generator), a new local named x is created in the scope of the assignment; Soft scope: If x is not already a local variable in the current or any outer scope, and all of the scope constructs containing the assignment are soft scopes (loops, try/catch blocks, or struct blocks), the behavior depends on whether the global variable x is defined: Let me know what you think. |
No, that's not the case. You can completely ignore hard/soft scope unless you're in the REPL or trying to shadow a global variable with the same name as a local variable. It does not matter whether the existing local is in this scope or an enclosing one, if it exists it is assigned to. Period, end of story. Comments on the edit suggestions...
This edit is incorrect: if the
This description is not how local variables or scopes work. Inner variables do not act as references to outer variables. The only question when it comes to matters of scope is "When I write
This edit does help clarify, we can make that change. The rest of the edits seem to do the same thing and add the phrase "in the current or any outer scope" after "already a local variable", which I guess helps clarify but it feels like we could maybe make this simpler by just explaining once that when we say that a local exists, that's what we mean. |
I have the feeling that the confusion might be caused by the very first statement of the paragraph: "A new local scope is introduced by most code blocks". That "new local scope" might be understood as a local scope disconnected from the outer one, such that it does not matter if
The last sentence is not directly related to the point made by @yygrechka, but I think it might also be a source of confusion. |
Yes, I like the edit that @heliosdrm proposes. That would make things clear. |
Based on my suggestion in JuliaLang#40238 (but with clearer wording I hope)
The documentation claims the following:
A new local scope is introduced by most code blocks (see above table for a complete list). Some programming languages require explicitly declaring new variables before using them. Explicit declaration works in Julia too: in any local scope, writing local x declares a new local variable in that scope, regardless of whether there is already a variable named x in an outer scope or not. Declaring each new local like this is somewhat verbose and tedious, however, so Julia, like many other languages, considers assignment to a new variable in a local scope to implicitly declare that variable as a new local.
https://docs.julialang.org/en/v1/manual/variables-and-scoping/#Local-Scope
Following my discussion here: https://discourse.julialang.org/t/referencing-local-variable-before-assignment-results-in-unexpected-behavior/58088/2, I'm given to understand that when functions are nested, inner functions can overwrite variables in the scope of the outer function.
This paragraph in the documentation makes it sound that the statement
x = 1
is equivalent tolocal x = 1
; I initially understood "new local"/"new variable" to mean a variable that is new to the scope that it is defined into.In the proceeding paragraph which seeks to spell out the exact rules for what happens when
x = <value>
, we have the following line:Existing local: If x is already a local variable, then the existing local x is assigned;
However, it is not clear if Existing local refers to the existing local within a particular scope block or within the outermost scope block.
e.g. consider the following code:
After engaging with Julia discourse, I understand that calling f2 will modify the x1 variable in the outermost scope, and so f() will return 3, however, after I initially read the documentation, I came out with the impression that calling f2() should not affect x1 in the outermost scope, and thus my initial impression was that f() should return 0.
The text was updated successfully, but these errors were encountered: