Renaming "it" to another name


#1

 

 
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.


#2

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


#3

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.


#4

 

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?


#5

No, you can not do that.


#6

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


#7

Looks functional enough to me already.


#8

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)
}


#9

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()`.


#10

Or better use first with filter:

services.first { it.name == serviceName }

#11

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)


#12

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.


#13

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


#14

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.


#15

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.