Renaming "it" to another name

 

 
public class Cache {
  private val services: List<Service>

  init {
  services = arrayListOf<Service>()
  }

  public fun getService(serviceName: String): Service? {
  services filter {
           service ->
           service.name.equals(serviceName, true)
  } forEach {
           service ->
           println(“Returning cached $serviceName object”)
           return service
  }

  return null
  }

  public fun addService(newService: Service) {
  var exists: Boolean = false

  services filter {
           service -> service.name.equals(newService.name)
  } forEach {
           exists = true
  }

  if (!exists)
           (services as MutableList).add(newService)
  }
}



In the above (getService method) as I could rename “it” for “service” only once? In this case I would use on the filter and forEach.

Could you give and example of the code that you would like to work?

In Swift you can do f.ex. this:

let numberOfLowercaseAs = "some chars".reduce(0) { $1 == "a" ? $0 + 1 : $0 }

Something like that might be an idea for Kotlin as well, I mean have it0, it1, it.

 

serviços filter {
  it.name.equals(serviceName, true)
} forEach {
  println(“Returning caches $serviceName object”)
  Returno it
)


The " it" is automatically generated. As I could rename “it” for another name (how “service”) and use on the methods filter and forEach without having to rename in each?

No, you can not do that.

How would you write the code above? Thinking of programming functional.

Looks functional enough to me already.

Maybe something like this:

data class Service(val name: String)

fun main(args: Array<String>) {
  val services = listOf(Service(“foo”), Service(“bar”), Service(“baz”))
  val serviceName = “bar”

  services.filter { service ->
  service.name == serviceName
  } forEach { service ->
  println(“returning caches ${serviceName} object”)
  println(service)
  }

  // returning caches bar object
  // Service(name=bar)
}

Also: You can use `first()` instead `forEach()` to return the first service element.

services.filter { it.name == serviceName }.first()

Interestingly IDEA can't decide whether to use `kotlin.Iterable.first()` or `kotlin.List.first()`.

Or better use first with filter:

services.first { it.name == serviceName }

You could simplify `addService`:

  public fun addService(newService: Service) {   if (! services.any { it.name == newService.name }) {            (services as MutableList).add(newService)   }   }

(or even better, use a hashSet() and you can do this in constant time)

Interesting insight. I thought `as` will return a copy of the list as mutable list, since `listOf()` creates a read-only list. I thought `services` will not change in the example below. Now I understand, that the interface just forces the list to be read-only.

val services = listOf(Service("foo"), Service("bar")) (services as MutableList).add(Service("baz")) println(services) // [Service(name=foo), Service(name=bar), Service(name=baz)]

Groovy differs here in behavior:

def services = ["foo", "bar"] (services as List).add("baz") println services // [foo, bar, baz]

def services = [“foo”, “bar”]
(services as Set).add(“baz”)
println services // [foo, bar]


Groovy will try to convert the object to another type, if the object is not castable to another type. Kotlin will raise a ClassCastException if the object is not castable.

I think the Kotlin behavour is better, since it is more predictable.

The fact that the list returned by "listOf" is mutable is an implementation detain and may be changed later

Yes. I was just copy/pasting the original code, but I think the type cast here is dangerous and should be removed. If you know your list is mutable, use `arrayListOf` instead of `listOf`, or -- as Andrey hints -- your code might break in the future.

Do not repair the code, was following a tutorial on Design Patterns. The code was in Java, I just modified to Kotlin.

I like your suggestion.