Since iter is passed as a parameter to opt_fun, the reference to iter in iter += 1 is to the parameter and not the global variable. The Int parameter is copied each invocation. The variable iter “shadows” the global variable of the same name.
In the case of the array, the iter array points to the same allocated block of memory and is unchanging during execution (whether copied or shadowed). The changing element is iter[1].
The first Int version would work if the iter parameter to opt_fun is removed, and the function accesses the global variable directly (which it is allowed to). Using global variables is not recommended though. And if done, it is best for performance to define them in a typed manner: iter::Int = 1.
Hope this clarifies things enough.