Как начать учиться в Scala? - PullRequest
0 голосов
/ 18 февраля 2019

У меня есть класс случайных чисел, который генерирует случайное число. Однако, я хочу, чтобы оно было Инициировано как член класса, чтобы нам не нужно было перегенерировать при каждом вызове. Ниже приведен код.

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

}

Я новичок в scala, мне нужно предложение. Какие изменения я должен сделать здесь?

Ответы [ 3 ]

0 голосов
/ 18 февраля 2019

Я пытался, как показано ниже, это будет работать нормально, или здесь я делаю что-то не так:

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
  }
}
0 голосов
/ 18 февраля 2019

Это в основном ответ на ваш собственный ответ, но он не помещается в комментарии.

  1. В Scala есть встроенная и поточно-ориентированная альтернатива тому, что вы делаете сvar _instance и def instance: lazy val.Используя его, мы получаем

    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. Поскольку вам всегда нужно инициализировать экземпляр при использовании RandomNumberModel, вы на самом деле не получаете никакой выгоды от lazy для этого случая,только незначительные накладные расходы.Не ленивые val в сопутствующем объекте инициализируются только при загрузке класса, например, когда вы создаете первый экземпляр класса.Так что просто сделайте private val instance : Random = scala.util.Random.

  3. Вам не нужно хранить ссылку, которая всегда указывает на один и тот же экземпляр в классе, это просто тратит впустую память.Лучше использовать RandomNumberModel.instance напрямую

    case class RandomNumberModel() extends Model{
        def apply(input: String):  Double  = {
            RandomNumberModel.instance.nextFloat // why not nextDouble?
        }
    
        ...
    }
    
  4. У вас есть несколько моделей, использующих один и тот же Random.Если ваша программа когда-либо имеет несколько потоков, манипулирующих моделями, обратите внимание

    Экземпляры java.util.Random являются поточно-ориентированными.Однако одновременное использование одного и того же экземпляра java.util.Random между потоками может привести к конфликту и, как следствие, к низкой производительности.

    Если вы используете ThreadLocalRandom, он обрабатываетсама инициализация:

    case class RandomNumberModel() extends Model{
        def apply(input: String):  Double  = {
             ThreadLocalRandom.current.nextFloat
        }
    
        ...
    }
    
    // object RandomNumberModel is gone
    
  5. Хотите ли вы, чтобы все RandomNumberModel были равны?Если нет, не делайте это case class.

0 голосов
/ 18 февраля 2019

Попробуйте

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

}
...