Julia: Bug Conditionally assigning a global variable inside closure gives UndefVarError

Created on 2 May 2017  Â·  9Comments  Â·  Source: JuliaLang/julia

If a global variable is defined outside of a closure and only "conditionally defined" inside the closure an UndefVarError is thrown.

bla = 1
map([1]) do x
  isdefined(:bla) || (bla=2)
  println(bla)
end
ERROR: UndefVarError: bla not defined
 in (::##1#2)(::Int64) at ./REPL[2]:6
 in _collect(::Array{Int64,1}, ::Base.Generator{Array{Int64,1},##1#2}, ::Base.EltypeUnknown, ::Base.HasShape) at ./array.jl:379
 in map(::Function, ::Array{Int64,1}) at ./abstractarray.jl:1803
Julia Version 0.6.0-pre.beta.401
Commit 96608db (2017-04-28 14:18 UTC)
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: Intel(R) Core(TM) i7-4600U CPU @ 2.10GHz
  WORD_SIZE: 64
  BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell)
  LAPACK: libopenblas64_
  LIBM: libopenlibm
  LLVM: libLLVM-3.9.1 (ORCJIT, haswell)

Note that the code does not what I intended it to do (overwrite bla), but its still incorrect behaviour I would say.

Most helpful comment

  1. A variable is either a global variable or a local variable (for the function)
  2. There's no magic automatic assignment from a global variable to a local variable

These two rules make the behavior easy to predict and rules out the behavior you want.

All 9 comments

This is expected behavior.

  1. The function is not a closure.
  2. bla is a local variable and not a global one in the function since it is assigned to in the function and not declared as global in the function
  3. isdefined check for global variable.

Ref https://docs.julialang.org/en/latest/devdocs/functions.html#Closures-1 (search closure) (the function does not capture any variable since it is directly under global scope)

https://docs.julialang.org/en/latest/manual/variables-and-scoping.html#Hard-Local-Scope-1 (search scoppe)
and then https://docs.julialang.org/en/latest/stdlib/base.html#Core.isdefined (search isdefined).

Why is that expected? If bla is not defined globally I might want it to define it locally and use that value. If it is defined globally however I want to use the global value. I know that after the map call bla will still be 1. Its certainly a corner case, but I don't see why this behaviour is expected.

It's expected and a good thing. If local variables bound to global variables by default, that would cause all sorts of havok; imagine if running norm = x^2 + y^2 in your function overwrote the global norm binding (to the function norm)! You can explicitly set a global variable locally by using the global keyword.

To be clear, this has nothing to do with the if condition. Assignments to variables in a function are never global by default.

I agree that local variables should not bound to globals for the reasons you mention. And as I said I don't expect bla=2 to modify the global bla, but I expect bla to be defined to 2 inside the anonymous function.

I don't agree that my case has nothing to do with the if. If one removes it and just writes bla=2 (i.e. condition is true) there is no error. If one removes it and additionally removes bla=2 there is also no error.

This is not a bug since it is intentional (and thoroughly documented). The merits of the design of scoping in the language would be better discussed on Discourse.

  1. A variable is either a global variable or a local variable (for the function)
  2. There's no magic automatic assignment from a global variable to a local variable

These two rules make the behavior easy to predict and rules out the behavior you want.

@tehrengruber: you may be intuitively expecting something like dynamic scoping, but that was found to be quite problematic in early Lisps despite being intuitive and fell out of favor long ago.

@yuyichao that was contrary to my expectations and @StefanKarpinski link explains nicely why its good that this does not work. Thanks for pointing this out so clearly. I should probably need to change my workflow into something like Gitter -> Discourse -> Issue...

Was this page helpful?
0 / 5 - 0 ratings