1

I want to reshape a matrix inside of a function, so I "declared" an array outside of the function and used reshape() in the function. It doesn't really work, even though array is mutable.

julia> my_array = 1:10
1:10

julia> function test(array)
           array = reshape(array, 2, 5)
           println(array)
       end
test (generic function with 1 method)

julia> test(my_array)
[1 3 5 7 9; 2 4 6 8 10]

julia> println(my_array)
1:10

Inside of the function, my_array has been reshaped into a 2*5 matrix, but it restores the 1:10 after executing the function.

I am wondering the reason behind that, and how can I reshape a global array inside of function?

EDIT: My problem is different from variable references in lisp, I know the idea of passing a copy of variable into stack. For this problem, I don't know why the specific function reshape() does not change array's contents, even if I pass the reference of a mutable object.

Community
  • 1
  • 1
Jay Wang
  • 2,650
  • 4
  • 25
  • 51
  • Possible duplicate of [Variable references in lisp](http://stackoverflow.com/questions/1249991/variable-references-in-lisp) – Kaz Dec 28 '16 at 18:47

2 Answers2

5

From the docs:

Suppose you call a function like this:

julia> x = 10
10

julia> function change_value!(y)
           y = 17
       end
change_value! (generic function with 1 method)

julia> change_value!(x)
17

julia> x # x is unchanged!
10

In Julia, the binding of a variable x cannot be changed by passing x as an argument to a function. When calling change_value!(x) in the above example, y is a newly created variable, bound initially to the value of x, i.e. 10; then y is rebound to the constant 17, while the variable x of the outer scope is left untouched.

Thus you cannot reassign a variable by reassigning the passed value within the function.

That being said, some collections allow mutations (but still no reassignment):

julia> function mut(x)
       x[1] = 100
       end
mut (generic function with 1 method)

julia> a = [1,2,3]
3-element Array{Int64,1}:
 1
 2
 3

julia> mut(a)
100

julia> a
3-element Array{Int64,1}:
 100
   2
   3

If you want to change the array itself and get some other answer you can use a tuple to return multiple values:

julia> function dubSum(x)
           x = hcat(x,x)
           sum_val = sum(x)
           return (x, sum_val)
       end
dubSum (generic function with 1 method)

julia> x = [1,2,3]
3-element Array{Int64,1}:
 1
 2
 3

julia> x, sum_val = dubSum(x)
(
3x2 Array{Int64,2}:
 1  1
 2  2
 3  3,

12)

julia> x
3x2 Array{Int64,2}:
 1  1
 2  2
 3  3

julia> sum_val
12
evan.oman
  • 5,922
  • 22
  • 43
3

I am wondering the reason behind that, and how can I reshape a global array inside of function?

reshapeing in general is not type stable if it was mutable: here you show that you change a vector into matrix, so the type would have had to change. That's why reshape returns instead of mutates since type-stability is so central to Julia programming.

However, reshape actually returns a view, so you can check that v = reshape(A,...) doesn't actually copy any data: it just creates a new type which defines a new indexing scheme. Since arrays are passed by reference (i.e. by pointer), there's really no cost to returning the reshaped type. So to get the behavior you want without performance problems, the answer is just to catch the returned type:

function test(array)
  array = reshape(array, 2, 5)
  array
end
reshaped = test(array)
Community
  • 1
  • 1
Chris Rackauckas
  • 18,645
  • 3
  • 50
  • 81
  • 1
    In addtion to Chris' comments, another issue is that you are passing a `UnitRange`, so that if you tried to modified the values of the passed in array after reshaping it, in that case it would not work. – Scott Jones Dec 29 '16 at 14:52