Scala - mutable (var) method parameter reference
You can't.
You'll have to declare an extra var
(or use a more functional style :-)).
Simplistic example:
def save(srcPath: String, destPath: String) {
val normalizedDestPath =
if (destPath.endsWith('/')) destPath
else destPath + '/'
// do something with normalizedDestPath
}
The JVM does not allow pass-by-reference of pointers to objects (which is how you'd do this in C++), so you can't do exactly what you want.
One option is to return the new value:
def save(srcPath: String, destPath: String): String = {
val newPath = (if (!destPath.endsWith("/")) destPath+'/' else destPath)
// do something
newPath
}
Another is to create a wrapper:
case class Mut[A](var value: A) {}
def save(srcPath: String, destPath: Mut[String]) {
if (!destPath.value.endsWith("/")) destPath.value += '/'
// do something
}
which users will then have to use on the way in. (Of course, they'll be tempted to save("/here",Mut("/there"))
which will throw away the alterations, but this is always the case with pass-by-reference function arguments.)
Edit: what you're proposing is one of the biggest sources of confusion among non-expert programmers. That is, when you modify the argument of a function, are you modifying a local copy (pass-by-value) or the original (pass-by-reference)? If you cannot even modify it it is pretty clear that anything you do is a local copy.
Just do it that way.
val destWithSlash = destPath + (if (!destPath.endsWith("/")) "/" else "")
It's worth the lack of confusion about what is actually going on.
Maybe you could get the type system to do the work for you, so you don't even need to worry about adding a slash each time:
class SlashString(s: String) {
override val toString = if (s endsWith "/") s else s + "/"
}
implicit def toSlashString(s: String) = new SlashString(s)
Now you don't need any code at all to change the input String
:
def save(srcPath: String, destPath: SlashString) {
printf("saving from %s to %s", srcPath, destPath)
}
val src: String = "abc"
val dst: String = "xyz"
scala> save(src, dst)
saving from abc to xyz/
True, there's a bit of setup at the start, but this will be less-so with implicit classes in version 2.10, and it removes all clutter from the method, which was what you were worried about.
String objects are immutable in Scala (and Java). The alternatives I can think of are:
- Return the result string as return value.
- Instead of using a String parameter, use a StringBuffer or StringBuilder, which are not immutable.
In the second scenario you would have something like:
def save(srcPath: String, destPath: StringBuilder) {
if (!destPath.toString().endsWith("/"))
destPath.append("/")
// do something
//
}
EDIT
If I understand correctly, you want to use the argument as a local variable. You can't, because all method arguments are val's in Scala. The only thing to do is to copy it to a local variable first:
def save(srcPath: String, destPath: String) {
var destP = destPath
if (!destP.endsWith("/"))
destP += "/"
// do something
//
}