2
votes

I am trying to use all features of kotlin, but seems not of them are working, or may be it's my fault.

So, apply to String not work. Example:

val str = someStr.apply {
    toUpperCase()
    if (contains("W")) replace("W", "w")
}

Input -> xywz

Output -> xywz

Expected -> XYwZ

Java style:

val str = it.text().toString().toUpperCase()
if (str.contains("W")) str.replace("W", "w")

Input -> xywz

Output -> XYwZ

Expected -> XYwZ

Am I doing something wrong?

3
You're looking for fancy ways to do simple things. Just take a look at TheOperator's answer.user8959091

3 Answers

4
votes

toUpperCase() returns a copy of the string (strings are immutable). So you need to store the returned value, as a stand-alone (not last) statement inside apply() it is lost.

Also, you can't use if without else, if you return an expression. The contains() is not even needed in your case.

What you probably would like to do is call toUpperCase() and replace() directly:

val str = someStr.toUpperCase().replace("W", "w")
4
votes

Actually apply does not return the value you calculated. You may rather want to use either: run, let or with. Additionally, probably more important, is that you do not specify an else path. That might return you a Unit instead of a value, so you may want to specify what should be returned otherwise. Finally, the calls within those methods are not chained. Calling toUpperCase first doesn't alter anything... It's nearly dead code... So you may want to write something like:

val str = with(someStr) {
  toUpperCase().run {
    if (contains("W")) replace("W", "w")
    else this
  }
}

However I just used run/let/with to demonstrate its usage, as you already used apply... your shown Java way is of course way easier in this regard and the simplest possible solution is rather the one TheOperator showed by just omitting your condition in the first place as the replace is case-sensitive by default.

1
votes

Docs of "apply" :

Calls the specified function block with this value as its receiver and returns this value.

So it returns the original value ("this value").

What you should use is "let" instead:

val str = someStr.let {
    it.toUpperCase().replace("W", "w")
}

But then you could just use:

val str = someStr.toUpperCase().replace("W", "w")