繁体   English   中英

随机选择scala案例类

[英]Random selection of scala case class

我正在开发遗传算法,并希望从以下随机选择案例类

sealed abstract class Gene(val code: Int)

object Gene {

  case object None extends Gene(0)

  case object Identity extends Gene(1)

  case object Squared extends Gene(2)

  case object Cubed extends Gene(3)

  case class Exp(a: Double) extends Gene(4)
}

如何列出并随机选择它们?

PS

无法使用枚举,因为我将实现Gene参数和方法

PS2

以下是我写的,它需要在改变基因时手动编辑,但它可能是简单的解决方案......

def getRandomGene(scaleFactor: Double): Gene = {
  Random.nextInt(5) match {
    case 0 => None
    case 1 => Identity
    case 2 => Squared
    case 3 => Cubed
    case 4 => Exp(scaleFactor / 10 + Random.nextDouble() * 9.9 * scaleFactor)
  }
}

根据Travis Brown回答“Scala密封特性的迭代”( https://stackoverflow.com/a/13672520/1637916 )以及关于scala宏的我(差)知识的问题,我写了一个简单的select和随机方法。

“select”方法(来自Sealed对象)返回具有指定参数的构造函数的案例类(或对象)的实例列表。 “select”不能返回一个随机的实现,因为它在编译时工作并且总是会返回它 - 对于每次调用。

“随机”方法(来自RanomElement对象)从“select”方法返回的List中选取一个对象。

应首先编译Sealed.scala文件。 如果您尝试同时编译两个文件(Sealed.scala和RandomGene.scala),您将看到以下错误:

Error:(34, 27) macro implementation not found: select
(the most common reason for that is that you cannot use macro implementations in the same compilation run that defines them)
      select[Gene]().random
  1. Sealed.scala包含select
import scala.language.experimental.macros
import scala.reflect.internal.Symbols
import scala.reflect.macros.whitebox

/**
  * Based on Travis Brown answer to the following question:
  * https://stackoverflow.com/questions/13671734/iteration-over-a-sealed-trait-in-scala (https://stackoverflow.com/a/13672520/1637916)
  */
object Sealed {

  def select[A](param: Any*): List[A] = macro select_impl[A]

  def select_impl[A: c.WeakTypeTag](c: whitebox.Context)(param: c.Expr[Any]*): c.Expr[List[A]] = {
    import c.universe._

    val symbol = weakTypeOf[A].typeSymbol

    if (!symbol.isClass) c.abort(
      c.enclosingPosition,
      "Can only enumerate values of a sealed trait or class."
    )
    else if (!symbol.asClass.isSealed) c.abort(
      c.enclosingPosition,
      "Can only enumerate values of a sealed trait or class."
    )
    else {
      val children = symbol.asClass.knownDirectSubclasses.toList

      val matchedChildren = children.filter { child =>
        child.asType.toType.members.filter(s => s.isConstructor && s.owner == child).exists {
          _.asMethod.paramLists match {
            case head :: Nil =>
              val constructorTypes = head.map(_.typeSignature)
              val paramTypes = param.map(_.actualType)

              constructorTypes.size == paramTypes.size && constructorTypes.zip(paramTypes).count { case (t1, t2) => t1 == t2 } == paramTypes.size
            case _ => false
          }
        }
      }

      c.Expr[List[A]] {
        def sourceModuleRef(sym: Symbol) = {
          if(param.nonEmpty) {
            Apply(
              Select(
                Ident(sym.companion),
                TermName("apply")
              ),
              param.map(_.tree).toList
            )
          } else {
            Ident(sym.asInstanceOf[Symbols#Symbol].sourceModule.asInstanceOf[Symbol])
          }
        }

        Apply(
          Select(
            reify(List).tree,
            TermName("apply")
          ),
          matchedChildren.map(sourceModuleRef(_))
        )
      }
    }
  }
}
  1. 随机
implicit class RandomSealed[A](ls: List[A]) {
  def random = ls(Random.nextInt(ls.size))
}
import scala.language.experimental.macros
import scala.util.Random

object RandomGene {

  sealed abstract class Gene(val code: Int)

  object Gene {
    case object None extends Gene(0)

    case object Identity extends Gene(1)

    case object Squared extends Gene(2)

    case object Cubed extends Gene(3)

    case class Exp(a: Int, b: String) extends Gene(a)

    case class Exp1(b: String, a: Int) extends Gene(a)

    case class Exp2(a: Int) extends Gene(a)
    case class Exp3(a: Int) extends Gene(a)
    case class Exp4(a: Int) extends Gene(a)
  }

  implicit class RandomElement[A](ls: List[A]) {
    def random = ls(Random.nextInt(ls.size))
  }

  def main(args: Array[String]) {
    import Sealed._

    (1 to 5).foreach { n =>
      println(select[Gene]().random)
    }

    (1 to 5).foreach { n =>
      println(select[Gene](n).random)
    }
  }

}

制作每个的apply方法的集合,并随机选择一个并将参数传递给它

像List((Identity.apply _),(Square.apply _,...)之类的东西

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM