Dynamic mixin in Scala - is it possible? -


what i'd achieve having proper implementation for

def dynamix[a, b](a: a): b 

i may know b is, don't know (but if b has self type add constraints on a). scala compiler happy above signature, not yet figure out how implementation - if possible @ all.

some options came mind:

  • using reflection/dynamic proxy.
    • simplest case: interface on java level + can instantiate b , has no self type. guess not hard (unless run nasty, unexpected problems):
      create new b (b), , proxy implementing both , b , using invocation handler delegating either or b.
    • if b can not instantiated still create subclass of it, , described above. if has self type need delegation here , there, may still work.
    • but if concrete type , can't find proper interface it?
    • would run more problems (e.g. related linearization, or special constructs helping java interoperability)?
  • using kind of wrapping instead of mixin , return b[a], accessible b.
    unfortunately in case caller need know how nesting done, quite inconvenient if mixing in/wrapping done several times (d[c[b[a]]]) need find right level of nesting access needed functionality, don't consider solution.
  • implementing compiler plugin. have 0 experience gut feeling not trivial. think kevin wright's autoproxy plugin has bit similar goal, not enough problem (yet?).

do have other ideas might work? way recommend? kind of "challenges" expect?
or should forget it, because not possible current scala constraints?

intention behind problem: have business workflow, it's not strict. steps have fixed order, others not, @ end of them has done (or of them required further processing).
bit more concrete example: have a, can add b , c it. don't care done first, @ end i'll need b c.

comment: don't know groovy popped this question , guess it's more or less same i'd like, @ least conceptional.

i believe impossible strictly @ runtime, because traits mixed in @ compile-time new java classes. if mix trait existing class anonymously can see, looking @ classfiles , using javap, anonymous, name-mangled class created scalac:

class foo {   def bar = 5 }  trait spam {   def eggs = 10 }  object main {   def main(args: array[string]) = {     println((new foo spam).eggs)   } } 

scalac mixin.scala; ls *.class returns

foo.class main$.class spam$class.class main$$anon$1.class main.class spam.class

while javap main\$\$anon\$1 returns

compiled "mixin.scala"  public final class main$$anon$1 extends foo implements spam{     public int eggs();     public main$$anon$1(); } 

as can see, scalac creates new anonymous class loaded @ runtime; presumably method eggs in anonymous class creates instance of spam$class , calls eggs on it, i'm not sure.

however, can pretty hacky trick here:

import scala.tools.nsc._; import scala.reflect.manifest  object dynamicclassloader {   private var id = 0   def uniqueid = synchronized {  id += 1; "klass" + id.tostring } }  class dynamicclassloader extends      java.lang.classloader(getclass.getclassloader) {   def buildclass[t, v](implicit t: manifest[t], v: manifest[v]) = {      // create unique id     val id = dynamicclassloader.uniqueid      // what's scala code need generate class?     val classdef = "class %s extends %s %s".       format(id, t.tostring, v.tostring)      println(classdef)      // fire new scala interpreter/compiler     val settings = new settings(null)     val interpreter = new interpreter(settings)      // define class     interpreter.compileandsaverun("<anon>", classdef)      // bytecode new class     val bytes = interpreter.classloader.getbytesforclass(id)      // define bytecode using classloader; cast expect     defineclass(id, bytes, 0, bytes.length).asinstanceof[class[t v]]   }  }   val loader = new dynamicclassloader  val instance = loader.buildclass[foo, spam].newinstance instance.bar // int = 5 instance.eggs // int = 10 

since need use scala compiler, afaik, close cleanest solution this. it's quite slow, memoization greatly.

this approach pretty ridiculous, hacky, , goes against grain of language. imagine sorts of weirdo bugs creep in; people have used java longer me warn of insanity comes messing around classloaders.


Comments

Popular posts from this blog

Android layout hidden on keyboard show -

google app engine - 403 Forbidden POST - Flask WTForms -

c - Why would PK11_GenerateRandom() return an error -8023? -