Why does this function change the input?

State=[[1,2,3],,];

function move(State,m,n)
if checkLegal(State,m,n)>0
State[n]=[State[m][1];;State[n]]
State[m]=State[m][2:end]
end
return State
end

I’m trying to get a new state
newState=move(State,1,2)

This changes the State variable for some reason even though the variable being modified is implied in function-scope. Could anyone please tell me why this is the case and how to write a function that doesn’t change the global variable?

Was missing the definition of checkLegal. Here it is

function checkLegal(State,m,n)
if State[m]==
return 0
elseif State[n]==
return 1
elseif State[m][1]>State[n][1]
return 0
else
return 1
end
end

You’re explicitly mutating the array you pass in, so it’s not surprising that it’s mutated. Why did you expect that mutating your input would leave it unchanged? Do you come from a different language where arrays passed to functions behave that way? Maybe matlab?

1 Like

I was under the impression that unless followed by a ! functions don’t mutate the arguments that are passed to them. Do Julia functions normally do this?

The exclamation mark is only a convention, it does not have any semantic consequences whatsoever.

5 Likes

I have often missed an explanation mark in the language. Good to know it’s coming along😁

2 Likes

As written, the exclamation mark is convention only. In other words, Julia functions can do whatever they want, including mutating their inputs, and it’s a convention that a programmer that makes a mutating function for which a non mutating version can exist to end its name with an explanation mark. In other words, it’s the responsibility of the programmer to add the exclamation mark to the mutating function they create. And to create non mutating functions if they don’t want them to change their inputs.

1 Like

To return a modified array without mutating the input argument, you can make a copy:

checkLegal(state,m,n) = !isempty(state[m]) && (isempty(state[n]) || state[m][1] <= state[n][1])

function move(state,m,n)
    result = copy(state)
    if checkLegal(state,m,n)
        result[n] = [state[m][1]; state[n]]
        result[m] = state[m][2:end]
    end
    return result
end

Note that copy doesn’t create copies of the inner arrays, it makes a copy of state which points to the same arrays. But since you are not mutating the inner arrays, only reassigning to them, it shouldn’t matter.

4 Likes

Yes.

Argument Passing Behavior
Julia function arguments follow a convention sometimes called “pass-by-sharing”, which means that values are not copied when they are passed to functions. Function arguments themselves act as new variable bindings (new locations that can refer to values), but the values they refer to are identical to the passed values. Modifications to mutable values (such as Arrays) made within a function will be visible to the caller. This is the same behavior found in Scheme, most Lisps, Python, Ruby and Perl, among other dynamic languages.
Functions · The Julia Language

2 Likes