Julia: Type annotations in global scope

Created on 22 Jun 2012  路  14Comments  路  Source: JuliaLang/julia

Is it expected behaviour that I can't type annotate variable declarations in global scope? Example:

julia> foo::Float = 0.1
foo not defined

julia> function bar()
         foo::Float = 0.1
       end

julia> bar()
0.1
performance

Most helpful comment

Or better yet: add proper support for it.

All 14 comments

It is expected insofar as that we are aware of the issue. Currently using global variables kills performance specifically because they are of unknown type. Type annotations on global variables are a planned feature but IIRC, there was some technical limitation (maybe @JeffBezanson can go into detail on that).

Hope that helps.

Planned feature.

Further plan: make globals type-const by default. That is, writing

glb = x

is equivalent to this:

glb::typeof(x)
glb = x

unless there was some prior declaration of the type of glb. If you want an global that can hold different types of values, you must explicitly annotate that:

glb = 1      # not const but has to be Int
glb::Any     # can hold anything
glb::String  # can hold any kind of string

This approach will alleviate the horrific performance trap that global variables currently constitute. Most globals are actually constant and they hardly ever change type.

The current workaround is to declare globals as const, but this is unsatisfactory in many situations where the value of the global may change but its type does not.

I keep running into this problem in modules, in which the module needs to do some run-time initialization and cache the results in a global, but the only way to do this without screwing the compiler seems to be to annotate every place that the global is used, which is annoying.

Please don't let this issue fall off the queue.

I'm not sure if this is entirely kosher but I have found that I can declare an array as const and still change the values of elements of the array. In the CHOLMOD code all the C functions have an argument which is a pointer to this horribly long cholmod_common struct and many of the optional arguments are changed by changing values in this struct. The way this is done in the extras/suitesparse.jl file in the db/suitesparse branch is to declare a const Uint8 array of the appropriate length and change the values of some parts of this array using reinterpret.

That is completely kosher 鈥撀爐he only thing that's const is the binding. The array itself is still a mutable thing. However, we still need this stuff.

A possibly related problem: you can't usefully declare type annotations with the global keyword either. e.g.

x=3
baz(y::Int) = begin
    global x::Int
    x+y
end

is accepted by the parser, but the type annotation on the global statement doesn't seem to accomplish much. If you run disassemble(baz, (Int,)), you will find that it is still nowhere near as efficient as baz(y::Int) = x::Int + y.

Hearty bump. I've recently been working on porting type-stability-sensitive C++ code where I use the pattern of:

function foo(args...)
    init::Uint64 = 1 # need to ensure init::Uint64 throughout function
...

But then when trying to debug, I can't run the lines one by one because just running

In  [99]:  init::Uint64 = 1

Out [99]: ERROR: init not defined
while loading In[99], in expression starting on line 1

It just makes type annotating a hassle because it's the right way to ensure the type stability of a variable, yet I can't switch between using it in function vs. global scope.

I've came to discover yet another workaround: using 0-dimensional arrays to store single boxed immutables:

const flag = Array(Bool)
.....
flag[] = true
......
if flag[] .....

About the "globals type-const by default" I think that not only it does not solve all problems but it will also break a little the REPL user experience...

Yes, that's a bit of a problem. The REPL experience would not be good with type-const by default.

I'm not sure why this is considered breaking. Just because we ignore it now? If so, can we at least make this syntax an error on globals so that it is no longer breaking and can be added in 1.1 instead of having to wait until 2.0? Alternatively, this just doesn't seem all that hard to implement.

This is no longer breaking after #17445.

Sometimes I just copy code from other people' s module to see the output. Can we make this a warning instead of error?

Or better yet: add proper support for it.

Was this page helpful?
0 / 5 - 0 ratings