Why it is possible to use a global variable in a custom function that declares later than the function declaration?

Hi Julianners, I am new to Julia.
Recently, I find it’s weird that I can use a global variable declares later when I am writing a function. Here is an example:

function p(a::Int)
    return a+b

b = 2
c = p(1)
@show c

It is quite different to what it is in C/C++ or Python. And makes me really confused.
Is that because the compiler ignores the function until it is being used, or some other reasons?
Is that for the same reason we can write export at the beginning of a module, before everything is declared.
Is that common or discouraged to use a global variable declares later while writing my functions? (so that I do not need to pass them as parameters)

1 Like

Global variables, in general, are discouraged (and have been in pretty much all programming for decades now).

In Julia, when you define your function p the compiler simply notes that when executed you want to look up whatever the value of b is at that time. You can see this by using @code_lowered:

@code_lowered p(1)
1 ─ %1 = a + Main.b
└──      return %1

It’s not necessary to declare variables ahead of time - in fact you don’t need to declare functions or anything else. For example:

f(a) = g(a)
g(a) = a + 1

This works fine as the compiler is happy to accept that when f is called it is to use whatever definition of g that it has at the time.

This is important for multiple dispatch. The precise method to call will depend on the types of the actual arguments - and this may not be known at time of declaration.

But please, reconsider the usage of global variables. There are many alternatives depending on the exact use-case.


thanks a lot for your helpful reply. :smiling_face_with_three_hearts:

1 Like

Just curious, but how is that different from Python?
For me, the following

def p(a):
  return a + b

b = 2
c = p(1)

works just the same.

PS: Also some compiled languages allow arbitrary forward declarations, e.g., in Haskell even this works:

main = putStrLn $ show c

p(a) = a + b

c = p(1)
b = 2

In the end, it’s more a restriction of the compiler than anything else.