Object not defined in Loop - julia

I create an object and then try to use it in a loop
a = 0
for i in 1:2
a += 1
end
However, this results in the following error:
UndefVarError: a not defined
Have I forgotten how loops work or what is going wrong?

The point is that your a is a global variable and in Julia versions between 1.0 and 1.4.2 the local scoping for variables within loops was introduced. More precisely if you do not explicitly say you want to mutate a global variable (global a += 1) a new variable within a local scope is introduced.
The best thing to do is to upgrade to Julia 1.5. Julia 1.5 has introduced back soft scoping in the REPL.
If you need to stick with the current Julia version you could use global keyword or place your code in a function or use Jupyter notebook instead (that has soft scoping) or surround your code around let...end block such as:
let
a = 0
for i in 1:2
a += 1
end
a
end

Related

Julia v1.6 update seems to have changed the rules for overwriting existing global variable in soft local scope

I've just updated Julia to v1.6.3 from v1.5.0 in Atom, and I'm running Julia in some script.jl file (I'm using shift+enter to run the highlighted code). According to Julia's documentation, for both two versions,
Julia Doc (v1.5.0 and v1.6.3)
So (if I understand the doc correctly) if you already have a global variable named x, and if you try to assign value to variable x in a for loop (which creates a soft scope) in non-interactive context, Julia will create another local variable x and the original global variable x would not be modified.
But I noticed same lines of code yield different outcomes in v1.5.0 and v1.6.3, the lines of code are as follows:
x = 0
for i = 1:10
x += 10
end
In v1.5.0, it would give me error saying "UndefVarError: x not defined", which makes sense since in the soft scope (within for loop), it would create a new local variable x, but we didn't assign value to this new local variable. But in v1.6.3, the code works out fine and x got change in global scope as well. I'm guessing instead of creating a new local variable x, it uses the global variable x and assigns value to that.
But I'm still not sure exactly what happened here, does this mean in v1.6.3 (and perhaps onwards), in a soft scope, we can directly use variable that is created in global scope and change its value without even yielding any warning? This change seems to me would cause more room for ambiguity.

I'm getting the following error: "top-level scope at ./REPL[1]:4" when I run my julia program

So here's the code I was trying to execute in Julia:
i = begin
i = 5
while(i<=10)
println(i)
i+=1
end
end
It's just basically a simple code to print the value of i from 5 to 10 but it's messing with me
Are you in the REPL? What you are probably running into is that begin does not introduce its own scope, so i = 5 declares i as a global variable. Because while does introduce its own scope, if you do println(i), it only looks for i in its local scope where it is not defined, because i exists only as a global variable. You can add a line global i at the beginning of the body of the while loop to tell all code after that to use the global i, but note that global variables come with their own performance caveats. An arguably better solution would be to use let instead of begin, which does introduce a new scope, but note that then you can of course not access i afterwards, because it is now only local to the let block.
This behavior will actually be changed in the upcoming release of Julia 1.5, so your code should then just work.
Your issue is scope. When you enter into a loop, variables created inside the loop are local to the loop and destroyed after it exits. i is not currently defined inside your while loop, so you get the error. The quick fix is to tell Julia you want the loop to have access to the global i variable you defined at the top by adding global i immediately after the while statement. You also don't need the begin block, and naming the block i is immediately overwritten by the next statement defining i.

Suppress deprecation warnings in Julia 0.6 without using `--depwarn=no` or a package

I am writing a tool in Julia that requires a package with a deprecated function.
My script is called from the command line and takes many arguments so I would like to avoid using --depwarn=no to suppress deprecation warnings.
Instead, I'd like to embed this --depwarn=no or somehow signal this into my script so the user doesn't have to type it in, or worry about it whenever they run the script.
Does anyone know how can I do this using only Base Julia without installing any another package like Suppressor.jl?
I wrote Suppressor initially, as far as I know there is no other way right now, which is why I started Suppressor.
You could always copy paste verbatim the suppress* macro you need, into your code (but I would advise just to use Suppressor honestly, in case of updates), all the Suppressor macros are self contained and require only Base (if you are on 0.6.x this macros shouldn't need Compat).
#suppress_err (latest version):
"""
#suppress_err expr
Suppress the STDERR stream for the given expression.
"""
macro suppress_err(block)
quote
if ccall(:jl_generating_output, Cint, ()) == 0
ORIGINAL_STDERR = STDERR
err_rd, err_wr = redirect_stderr()
err_reader = #async read(err_rd, String)
end
value = $(esc(block))
if ccall(:jl_generating_output, Cint, ()) == 0
redirect_stderr(ORIGINAL_STDERR)
close(err_wr)
end
value
end
end
If you just want to get rid of the deprecation warnings, then #suppress_err is all you need. There have been improvements recently on the current Julia master branch related to logging, but I haven't checked out those yet.

What does the "Base" keyword mean in Julia?

I saw this example in the Julia language documentation. It uses something called Base. What is this Base?
immutable Squares
count::Int
end
Base.start(::Squares) = 1
Base.next(S::Squares, state) = (state*state, state+1)
Base.done(S::Squares, s) = s > S.count;
Base.eltype(::Type{Squares}) = Int # Note that this is defined for the type
Base.length(S::Squares) = S.count;
Base is a module which defines many of the functions, types and macros used in the Julia language. You can view the files for everything it contains here or call whos(Base) to print a list.
In fact, these functions and types (which include things like sum and Int) are so fundamental to the language that they are included in Julia's top-level scope by default.
This means that we can just use sum instead of Base.sum every time we want to use that particular function. Both names refer to the same thing:
Julia> sum === Base.sum
true
Julia> #which sum # show where the name is defined
Base
So why, you might ask, is it necessary is write things like Base.start instead of simply start?
The point is that start is just a name. We are free to rebind names in the top-level scope to anything we like. For instance start = 0 will rebind the name 'start' to the integer 0 (so that it no longer refers to Base.start).
Concentrating now on the specific example in docs, if we simply wrote start(::Squares) = 1, then we find that we have created a new function with 1 method:
Julia> start
start (generic function with 1 method)
But Julia's iterator interface (invoked using the for loop) requires us to add the new method to Base.start! We haven't done this and so we get an error if we try to iterate:
julia> for i in Squares(7)
println(i)
end
ERROR: MethodError: no method matching start(::Squares)
By updating the Base.start function instead by writing Base.start(::Squares) = 1, the iterator interface can use the method for the Squares type and iteration will work as we expect (as long as Base.done and Base.next are also extended for this type).
I'll grant that for something so fundamental, the explanation is buried a bit far down in the documentation, but http://docs.julialang.org/en/release-0.4/manual/modules/#standard-modules describes this:
There are three important standard modules: Main, Core, and Base.
Base is the standard library (the contents of base/). All modules
implicitly contain using Base, since this is needed in the vast
majority of cases.

Julia: local in module scope

When generating a not explicitly generated version of a function, #ngenerate runs
eval(quote
local _F_
$localfunc # Definition of _F_ for the requested value of N
_F_
end)
Since eval runs in the scope of the current module, not the function, I wonder what is the effect of local in this context. As far as I know, the languange documentation only mentions the use of local inside function definitions.
To give some background why this question arose: I frequently need to code loops of the form
function foo(n::Int)
s::Int = 0
for i in 1:1000000000
for j in 1:n
s += 1
end
end
return s
end
where n <= 10 (of course, in my actual code the loops are such that they cannot just be reduced to O(1)). Because this code is very simple for the compiler but demanding at runtime, it turns out to be beneficial to simply recompile the loops with the required value of n each time foo is called.
function clever_foo(n::Int)
eval(quote
function clever_foo_impl()
s::Int = 0
for i in 1:1000000000
s += $(Expr(:call,:+,[1 for j in 1:n]...))
end
return s
end
end)
return clever_foo_impl()
end
However, I am not sure whether I am doing this the right way.
It's to prevent _F_ from being visible in the global method cache.
If you'll call clever_foo with the same n repeatedly, you can do even better by saving the compiled function in a Dict. That way you don't have to recompile it each time.

Resources