Question about global variable behavior


I am trying to code Cramer’s rule from linear algebra in Julia. I am running into some variable behavior I don’t quite understand. Here’s the code (forgive the lack of “verbatim” I’m not sure how to format in discourse):

using LinearAlgebra

A = Matrix([1 4 7; 2 8 5; 3 6 9;])
if det(A) == 0
return “not invertible, cannot use Cramer’s Rule”
# set b = something
b = [-1; 0; 1]
m = size(A)[1]
x =
for k in 1:m
global x
global A
println(“matrix A”)
An = A
An[:,k] = b
println(“Matrix An”)
xn = det(An)/det(A)
x = push!(x,xn)

I’m confused by the behavior of A. When I change An matrix A also changes. That’s not good! I tried looking up static variables in Julia but these don’t seem to work like Python.

Can anyone explain what’s going on here and how I fix it?

Gratefully, Brian

EDIT: I’ve fixed Cramer’s rule, but only … inelegantly. Really hoping to understand why setting An = A then changing An also changes A… I think this is called a pointer? Forgive me, I’m not experienced.

  1. To format code wrap it between triple ticks:
    at the beginning and at the end

    Will look like this:

    at the beginning and at the end
  2. This is not aboout global variables. When you do An = A you are giving a new name (An) to the same object in memory as A. So when you modify one you modify the other one as well.

    You want to do:

    An = copy(A)

This behavior is mentioned for example in the second point of this list: Noteworthy Differences from other Languages · The Julia Language

By the way this works the same in python, maybe you were thinking Matlab?:

In [3]: a = [[1, 1, 1], [2, 2, 2]]

In [4]: a
Out[4]: [[1, 1, 1], [2, 2, 2]]

In [5]: a1 = a

In [6]: a1[1][1] = 5

In [7]: a1
Out[7]: [[1, 1, 1], [2, 5, 2]]

In [8]: a
Out[8]: [[1, 1, 1], [2, 5, 2]]
1 Like

Thanks for the tip(s)!

As a previous Matlab user, it is strange to me that not copying is the default. I never want to rename a variable without copying it. Why would I want two different names for the same object?

One reason for me is typing convenience. Suppose I have a long-named struct long_named_struct containing an array sparams. If I pass the struct to a function, it may be more convenient to work with the array in the function as follows:

function func!(long_named_struct, x, y, ...)
    sp = long_named_struct.sparams # Short local name for use in func!
1 Like