Skip to content
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

local in global scope #10472

Closed
mauro3 opened this issue Mar 11, 2015 · 18 comments
Closed

local in global scope #10472

mauro3 opened this issue Mar 11, 2015 · 18 comments
Assignees
Labels
breaking This change will break code compiler:lowering Syntax lowering (compiler front end, 2nd stage) macros @macros
Milestone

Comments

@mauro3
Copy link
Contributor

mauro3 commented Mar 11, 2015

Using local in the global scope does not error but does not do anything either:

julia> local x = 10
10

julia> x
ERROR: x not defined

julia> module A
       local x = 10
       y = x+ 10
       end
ERROR: x not defined

I would think that either throwing an error on local x = 10 or just ignoring the local would be the right thing to do.

@mbauman
Copy link
Member

mbauman commented Jan 27, 2016

Fix was reverted in faae194.

@mauro3
Copy link
Contributor Author

mauro3 commented Jan 28, 2016

Related, this local statement should also error:

julia> begin 
       local x = 1
       y = x+1
       end
2

julia> x
ERROR: UndefVarError: x not defined

julia> y
2

or if not then it should error on y=x+1 as begin blocks should not influence scope.

@mauro3
Copy link
Contributor Author

mauro3 commented Feb 25, 2016

This came up on julia-users, below is a minimal test case. I think this is related, if not I can make a new issue. Note that it errors in 0.5 and works in 0.4. (If local were to error in begin-end blocks this should error, but differently.)

~/julia/issues >> julia5
               _
   _       _ _(_)_     |  A fresh approach to technical computing
  (_)     | (_) (_)    |  Documentation: http://docs.julialang.org
   _ _   _| |_  __ _   |  Type "?help" for help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 0.5.0-dev+2650 (2016-02-13 20:03 UTC)
 _/ |\__'_|_|_|\__'_|  |  Commit efc2efb* (11 days old master)
|__/                   |  x86_64-unknown-linux-gnu

julia> s = 0;

julia> begin
           local x = 1
           local val = for i=1:2
               s = x+s
           end
       end
ERROR: UndefVarError: s not defined
 [inlined code] from ./none:4
 in anonymous at ./no file:4294967295
 in eval(::Module, ::Any) at ./boot.jl:267

julia> 
~/julia/issues >> julia 
               _
   _       _ _(_)_     |  A fresh approach to technical computing
  (_)     | (_) (_)    |  Documentation: http://docs.julialang.org
   _ _   _| |_  __ _   |  Type "?help" for help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 0.4.3 (2016-01-12 21:37 UTC)
 _/ |\__'_|_|_|\__'_|  |  
|__/                   |  x86_64-unknown-linux-gnu

julia> s = 0;

julia> begin
           local x = 1
           local val = for i=1:2
               s = x+s
           end
       end

julia> 

@JeffBezanson JeffBezanson added this to the 1.0 milestone May 2, 2017
@JeffBezanson
Copy link
Member

Complication: we like to be able to paste code from functions into the REPL if possible, and disallowing local in global scope would make this possible less often.

@mauro3
Copy link
Contributor Author

mauro3 commented Jul 9, 2017

Ok, that would be a +1 for "just ignoring it". (Note though, because of hard & soft scope, copy-paste does not work always anyway.)

@JeffBezanson
Copy link
Member

JeffBezanson commented Aug 9, 2017

Looking back at my previous attempt to fix this, the real wrinkle is macros. A macro like @time needs to introduce new unique variables into the current scope. We don't want those to be global variables, since that would litter the global namespace with the macro's temporary variables. Nor can the macro wrap its output in let, since that would change the scope of the user's expression. So the only solution we currently have is to allow top-level expressions to contain a mix of local and global variables. In local scope this is not a problem, since "littering" a local scope with new temp variables is harmless.

The other possible solution would involve macro hygiene. Basically we'd want to implicitly wrap the result of a macro in something like a let block, but that only local-izes its own hygienic variables.

@mauro3
Copy link
Contributor Author

mauro3 commented Aug 10, 2017

So the only solution we currently have is to allow global begin ... end blocks to contain a mix of local and global variables.

So begin ... end does impact scope after all. Maybe this should be documented?

@JeffBezanson
Copy link
Member

What really happens is that if a top-level expression contains local x = ..., then that expression has its own local scope. I shouldn't have mentioned begin ... end blocks there, since that's not what triggers this behavior. As in your OP, local x = 10 by itself does the same thing, as would e.g. if y; local x = 10; end. So it's not a feature of begin itself.

@StefanKarpinski
Copy link
Member

Technically, changing this would be breaking, but it's a kind of weird thing to do. Should we just document local in global scope as having undefined behavior and then move this off the milestone?

@JeffBezanson
Copy link
Member

I propose removing this from the milestone. Nice to fully work out at some point, but doesn't seem crucial.

@JeffBezanson JeffBezanson added the triage This should be discussed on a triage call label Oct 26, 2017
@StefanKarpinski
Copy link
Member

Wouldn't it be fairly simple to just raise an error for local in global scope? Or is there some deeper complication that I'm missing here?

@JeffBezanson
Copy link
Member

It's currently useful for macros to expand to top-level expressions that contain local.

@StefanKarpinski
Copy link
Member

Ah, I see. Changing this does not actually seem at all pressing to me. I'd be fine with leaving this as-is with the justification that it makes macro stuff easier. What's the drawback of this feature?

@JeffBezanson
Copy link
Member

I don't see any major problems, it's just weird.

@StefanKarpinski
Copy link
Member

Whatever, let's just keep it then. I guess we can document that it may go away and then see how much stuff in the ecosystem breaks if we ever decide to change it and let that be the deciding factor on whether it's a 1.x change or a 2.0 change.

@StefanKarpinski StefanKarpinski removed the triage This should be discussed on a triage call label Nov 2, 2017
@JeffBezanson JeffBezanson removed this from the 1.0 milestone Nov 2, 2017
@StefanKarpinski StefanKarpinski added this to the 2.0+ milestone Nov 2, 2017
@JeffBezanson JeffBezanson added compiler:lowering Syntax lowering (compiler front end, 2nd stage) macros @macros labels Nov 2, 2017
@tpapp
Copy link
Contributor

tpapp commented Aug 13, 2020

Since it came up in two discussions today, I am wondering if this behavior could just be kept as it is, and documented in the docstring ?local as intentional:

  1. it helps with macros, and
  2. pasting code to the REPL from function bodies (so it fits in with the spirit of RFC: bring back v0.6 scope rules in the REPL #33864).

If there is agreement on this, I would be happy to do a PR to the docstring.

@StefanKarpinski
Copy link
Member

Note, however, that if you have local in a function body and cut-and-paste it, that generally won't work right.

@simeonschaub
Copy link
Member

simeonschaub commented Jan 12, 2022

I think this issue can just be closed? The current behavior seems quite reasonable to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking This change will break code compiler:lowering Syntax lowering (compiler front end, 2nd stage) macros @macros
Projects
None yet
Development

No branches or pull requests

7 participants