Scala: Dynamically generating match clauses for case classes -
i want use power of scala's pattern matching within set of `condition-action' rules. these rules not known in advance, rather generated @ runtime according complex critera. algorithmic generation mechanism can considered separate , not part of question, concerned how express via scala reflection/quasiquotes.
concretely, i'm looking generate case definitions (of general form case v0@x(v1,_,v2): x => f(v1,v2)
) @ runtime.
it presumably possible via toolbox.parse(str)
string generated @ runtime. however, if possible seem desirable incorporate greater degree of type-safety this:
more specifically, want case defs match against sealed case class hierarchy of terms (term,var(name: char),lit(value:int),group(a: term,b: term,c: term)
).
for example, generated case def in general, return function of none, or of v0,v1,v2:
t match { case v0@group(v1@_,v2@var('a')) => group(v2,v0,group(v1,var('z'),lit(17))) // etc }
i'm attempting follow through on description of quasiquotes case defs given here, syntax rather mind-bending (and eclipse scala 2.11 refuses show me types), below far i've got. specific questions embedded in code:
def dynamicmatch(condition: sometype, action: sometype, tb: toolbox) (t: term): option[term] = { // q1. type should condition , action maximum // typesafety in calling code? symbols? quasiquotes? // best combined single actual casedef? // hardcoded placeholder expression, in general: // q2. how bind in t, condition , action? val q"$expr match { case ..$cases }" = q"foo match { case _ : term => some(expr) case _ => none }" val cq"$pat1 => $body1" :: cq"$pat2 => $body2" :: nil = cases // q3. how should invoked return desired result? ??? }
there's shapeless example builds function invocation purpose of getting toolbox select typeclass based on runtime types.
you want build logic dynamically, you're having difficulty quasiquoting.
this something:
// classes sealed trait term case class lit(value: int) extends term case class group(a: term, b: term) extends term // build function hooks patterns other expressions def stagedtermfunction(t: term): option[term] = { // add lits val tt = tq"_root_.shapeless.examples.term" val lit = q"_root_.shapeless.examples.lit" val grp = q"_root_.shapeless.examples.group" val pat = pq"$grp($lit(x), $lit(y))" val add = cq"$pat => some($lit(x + y))" val default = cq"_ => none" val cases = add :: default :: nil val res = q"{ case ..$cases } : (($tt) => option[$tt])" val f = evaltree[term => option[term]](res) f(t) }
then doesn't blow up:
val t3: term = group(lit(17), lit(42)) val some(lit(59)) = stagedtermfunction(t3) assert(stagedtermfunction(lit(0)) == none)
if wanted manipulate symbolof[group]
might have convert sym.fullname
select
tree built q"name"
; think there's utility method somewhere.
Comments
Post a Comment