Skip to content

Instantly share code, notes, and snippets.

@retronym
Created April 13, 2013 11:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save retronym/5377978 to your computer and use it in GitHub Desktop.
Save retronym/5377978 to your computer and use it in GitHub Desktop.
sealed subclass copier
scala> object O {
| sealed abstract class Base;
| case class Foo(id: Int, b: String) extends Base
| case class Bar(id: Int, b: Boolean) extends Base
| }
defined module O
scala> import O._
import O._
scala>
scala> val cm = scala.reflect.runtime.currentMirror
cm: reflect.runtime.universe.Mirror = JavaMirror with scala.tools.nsc.interpreter.IMain$TranslatingClassLoader@4eb63dfe of type class scala.tools.nsc.interpreter.IMain$TranslatingClassLoader with classpath [(memory)] and parent being scala.tools.nsc.util.ScalaClassLoader$URLClassLoader@1ea01711 of type class scala.tools.nsc.util.ScalaClassLoader$URLClassLoader with classpath [file:/Library/Java/JavaVirtualMachines/1.6.0_37-b06-434.jdk/Contents/Classes/classes.jar,file:/Library/Java/JavaVirtualMachines/1.6.0_37-b06-434.jdk/Contents/Classes/ui.jar,file:/Library/Java/JavaVirtualMachines/1.6.0_37-b06-434.jdk/Contents/Classes/jsse.jar,file:/Library/Java/JavaVirtualMachines/1.6.0_37-b06-434.jdk/Contents/Classes/jce.jar,file:/Library/Java/JavaVirtualMachines/1.6.0_37-b06-434.jdk/Contents/Class...
scala> import cm.universe._
import cm.universe._
scala>
scala> val function: Function = {
| val base = typeOf[Base].typeSymbol.asClass
| val subs = base.knownDirectSubclasses.toList
|
| object copierNme {
| val x: TermName = "x"
| val base: TermName = "base"
| val id: TermName = "id"
| val newId: TermName = "newId"
| val copy: TermName = "copy"
| }
| def mkCase(subClass: Symbol) = {
| val bind = Bind(copierNme.x, Typed(Ident(nme.WILDCARD), Ident(subClass)))
| val copyApply = Apply(Select(Ident(copierNme.x), copierNme.copy), List(AssignOrNamedArg(Ident(copierNme.id), Ident(copierNme.newId))))
| CaseDef(bind, EmptyTree, copyApply)
| }
| val param1 = ValDef(Modifiers(Flag.PARAM), copierNme.base, TypeTree(typeOf[Base]), EmptyTree)
| val param2 = ValDef(Modifiers(Flag.PARAM), copierNme.newId, TypeTree(typeOf[Int]), EmptyTree)
| Function(List(param1, param2), Match(Ident(copierNme.base), subs map mkCase))
| }
function: cm.universe.Function =
((base: O.Base, newId: Int) => base match {
case (x @ (_: Bar)) => x.copy(id = newId)
case (x @ (_: Foo)) => x.copy(id = newId)
})
scala>
scala> import scala.tools.reflect.ToolBox
import scala.tools.reflect.ToolBox
scala> val tb = cm.mkToolBox()
tb: scala.tools.reflect.ToolBox[reflect.runtime.universe.type] = scala.tools.reflect.ToolBoxFactory$ToolBoxImpl@60b705e9
scala> val idCopier = tb.compile(function)().asInstanceOf[((Base, Int) => Base)]
idCopier: (O.Base, Int) => O.Base = <function2>
scala>
scala> idCopier(Foo(0, "a"), 1) // Foo(1,a)
res30: O.Base = Foo(1,a)
scala> idCopier(Bar(0, true), 2) // Bar(1, true)
res31: O.Base = Bar(2,true)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment