Search code examples
scalalambdafunctional-interfacesingle-abstract-method

Does scala cache conversions to functional interfaces


Scala 2.12 can automatically convert a lambda expression to an interface. E.g, I'm using:

import org.apache.kafka.common.serialization.{Deserializer, Serde, Serializer}
import scalapb.GeneratedMessageCompanion

class ProtoSerde[A <: scalapb.GeneratedMessage](implicit companion: GeneratedMessageCompanion[A])
  extends Serde[A] {
  override def serializer(): Serializer[A] = (_: String, data: A) => data.toByteArray

  override def deserializer(): Deserializer[A] = (_: String, data: Array[Byte]) => companion.parseFrom(data)
}

Will it automatically cache the instance of the created objects, so that a new object isn't allocated on every call. I.e. I want:

import org.apache.kafka.common.serialization.{Deserializer, Serde, Serializer}
import scalapb.GeneratedMessageCompanion

class ProtoSerde[A <: scalapb.GeneratedMessage](implicit companion: GeneratedMessageCompanion[A])
  extends Serde[A] {
  lazy val _serializer: Serializer[A] = (_: String, data: A) => data.toByteArray
  lazy val _deserializer: Deserializer[A] = (_: String, data: Array[Byte]) => companion.parseFrom(data)

  override def serializer(): Serializer[A] = _serializer

  override def deserializer(): Deserializer[A] = _deserializer
}

Will the compiler perform this optimization automatically, or do I have to do it myself?


Solution

  • def is not memoized to calling it will recompute value every time. It might be later optimized by JIT compiler.

    But there's a simpler solution to make properties of class memoized. Scala allows changing def to val while you override parent methods. It is also possible to add lazy modifier on extending class:

    class ProtoSerde[A <: scalapb.GeneratedMessage](implicit companion: GeneratedMessageCompanion[A])
      extends Serde[A] {
      override lazy val serializer: Serializer[A] = (_: String, data: A) => data.toByteArray
    
      override lazy val deserializer: Deserializer[A] = (_: String, data: Array[Byte]) => companion.parseFrom(data)
    }