Ashwin Padhy
Ashwin Padhy

Reputation: 111

How to Initiate as class member in scala?

I have a random number class which generate the random number.However i want it to be Initiate as class member so that we do not need to regenerate in every call.Below is the code at present.

import ml.combust.mleap.core.Model
import ml.combust.mleap.core.types._

case class RandomNumberModel() extends Model{

  def apply(input: String):  Double  = {
    val rnd = scala.util.Random
    return rnd.nextFloat
  }

  override def inputSchema: StructType = StructType("input" -> ScalarType.String).get

  override def outputSchema: StructType = StructType("output" -> ScalarType.Double ).get

}

I am new to scala need suggestion What changes i have to do here ?

Upvotes: 0

Views: 94

Answers (3)

Alexey Romanov
Alexey Romanov

Reputation: 170835

This is mostly a response to your own answer, but doesn't fit in a comment.

  1. Scala has a built-in and thread-safe alternative to what you do with var _instance and def instance: lazy val. Using it we get

    object RandomNumberModel {
      // private is still visible in the companion class
      private lazy val instance : Random = scala.util.Random
    }
    
    // in the class:
    val inst = RandomNumberModel.instance
    
  2. Since you always need to initialize the instance when you use RandomNumberModel, you actually don't get any benefit from lazy for this case, only some minor overhead. Non-lazy vals in the companion object are only initialized when the class is loaded, e.g. when you create the first instance of the class. So just do private val instance : Random = scala.util.Random.

  3. You don't need to store a reference which always points to the same instance in the class, this just wastes memory. Better use RandomNumberModel.instance directly

    case class RandomNumberModel() extends Model{
        def apply(input: String):  Double  = {
            RandomNumberModel.instance.nextFloat // why not nextDouble?
        }
    
        ...
    }
    
  4. You have multiple models using the same Random. If your program ever has multiple threads manipulating models, note

    Instances of java.util.Random are threadsafe. However, the concurrent use of the same java.util.Random instance across threads may encounter contention and consequent poor performance.

    If you use ThreadLocalRandom it handles the initialization itself:

    case class RandomNumberModel() extends Model{
        def apply(input: String):  Double  = {
             ThreadLocalRandom.current.nextFloat
        }
    
        ...
    }
    
    // object RandomNumberModel is gone
    
  5. Do you want all RandomNumberModels to be equal? If not, don't make it case class.

Upvotes: 1

Ashwin Padhy
Ashwin Padhy

Reputation: 111

I tried as below will this work fine or here i am doing anything wrong:

case class RandomNumberModel() extends Model{
    import RandomNumberModel._
    val inst = instance()

    def apply(input: String):  Double  = {
        inst.nextFloat
    }

    override def inputSchema: StructType = StructType("input" -> ScalarType.String).get

    override def outputSchema: StructType = StructType("output" -> ScalarType.Double ).get
}

object RandomNumberModel {
  private var _instance : Random = null
  def instance() = {
    if (_instance == null)
      _instance = scala.util.Random
    _instance
  }
}

Upvotes: 0

Dmytro Mitin
Dmytro Mitin

Reputation: 51693

Try

case class RandomNumberModel() extends Model {
  private val rnd = scala.util.Random

  def apply(input: String): Double = rnd.nextFloat

  override def inputSchema: StructType = StructType("input" -> ScalarType.String).get

  override def outputSchema: StructType = StructType("output" -> ScalarType.Double ).get

}

Upvotes: 3

Related Questions