I'm new to Vala, but I seem to be encountering a strange problem when I try to make modifications to a parameter variable within the function. For example, this doesn't work:
public string changeString(string input) {
input = input.down();
return input;
}
(I get this error:) Invalid assignment from owned expression to unowned variable: input = input.down();
However this does work:
public string changeString(string input) {
string temp = input;
temp = temp.down();
return temp;
}
Am I correct in thinking parameter variables can't be modified in Vala? And if so, why? And is there a better workaround than the one above?
Yes and no. Arguments in Vala are unowned by default (see https://live.gnome.org/Vala/Tutorial#Ownership if you don't know what that means). You can assign to unowned variables (including arguments), but you can only assign unowned values to unowned variables. The problem here is that the return value of string.down is owned, and you're trying to assign it to an unowned variable. This isn't allowed because then Vala would have no way of knowing whether or not it should free the string at the end of the method.
There are a couple ways around this. The first is make the argument owned:
public string changeString (owned string input) {
input = input.down ();
return input;
}
This isn't usually a good idea, since it means that when you call changeString Vala has to copy (g_strdup) the input string, which is kind of a waste.
A related feature is parameter direction (see https://live.gnome.org/Vala/Tutorial#Parameter_Directions). If you want to modify input in-place you could do something like this:
public void changeString (ref string input) {
input = input.down ();
}
Putting a copy of input in a temp variable (like you did in your second example) doesn't really make sense... it copies the string in the first line of the method and then immediately frees it when you overwrite temp in the next line). Something like this makes more sense:
public string changeString (string input) {
string temp = input.down ();
return temp;
}
Of course, you don't really need a temporary variable...
public string changeString (string input) {
return input.down ();
}