[英]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
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(_))
)
}
}
}
}
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.