gpt4 book ai didi

scala - 随机选择scala案例类

转载 作者:行者123 更新时间:2023-12-01 09:09:25 24 4
gpt4 key购买 nike

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

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)
}

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

附言

Enum不能用,因为我要实现Gene的参数和方法

附言2

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

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 对“Iteration over a sealed trait in Scala”(https://stackoverflow.com/a/13672520/1637916)问题的回答以及我对 scala 宏的(贫乏)知识,我编写了一个简单的 select 和 random 方法实现。

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

“随机”方法(来自 RanomElement 对象)从“选择”方法返回的列表中挑选一个对象。

应首先编译 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 contains 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))
}
  1. 例子
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)
}
}

}

关于scala - 随机选择scala案例类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33980413/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com