Created
April 13, 2013 11:11
-
-
Save retronym/5377978 to your computer and use it in GitHub Desktop.
sealed subclass copier
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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