- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Announcing autoproxy-lite
Tue, 2011-04-05, 15:30
I now have a (slightly restricted) version of the long awaited autoproxy plugin passing the first few basic tests.
The jar isn't yet formally published anywhere, but the GitHub project can be found here: https://github.com/kevinwright/Autoproxy-Lite (Requires SBT 0.7.6.RC0 and targets Scala 2.9.0.RC1)
For anyone who likes like on the bleeding edge, please feel free to try it out and send me all your bug reports :)
--
Kevin Wright
gtalk / msn : kev.lee.wright@gmail.comkev.lee.wright@gmail.commail: kevin.wright@scalatechnology.com
vibe / skype: kev.lee.wrightquora: http://www.quora.com/Kevin-Wright
twitter: @thecoda
"My point today is that, if we wish to count lines of code, we should not regard them as "lines produced" but as "lines spent": the current conventional wisdom is so foolish as to book that count on the wrong side of the ledger" ~ Dijkstra
The jar isn't yet formally published anywhere, but the GitHub project can be found here: https://github.com/kevinwright/Autoproxy-Lite (Requires SBT 0.7.6.RC0 and targets Scala 2.9.0.RC1)
For anyone who likes like on the bleeding edge, please feel free to try it out and send me all your bug reports :)
--
Kevin Wright
gtalk / msn : kev.lee.wright@gmail.comkev.lee.wright@gmail.commail: kevin.wright@scalatechnology.com
vibe / skype: kev.lee.wrightquora: http://www.quora.com/Kevin-Wright
twitter: @thecoda
"My point today is that, if we wish to count lines of code, we should not regard them as "lines produced" but as "lines spent": the current conventional wisdom is so foolish as to book that count on the wrong side of the ledger" ~ Dijkstra
Tue, 2011-04-05, 18:57
#2
Re: Announcing autoproxy-lite
"package" will run the tests and build the jars. The annotation sub-project provides the @proxy annotation, and the plugin project supplies the plugin proper.
packaging will initially fail when it tries to build the examples before the plugin jar is output. Running it a second time will work just fine.
On 5 April 2011 18:17, Roland Kuhn <google@rkuhn.info> wrote:
--
Kevin Wright
gtalk / msn : kev.lee.wright@gmail.com kev.lee.wright@gmail.commail: kevin.wright@scalatechnology.com
vibe / skype: kev.lee.wrightquora: http://www.quora.com/Kevin-Wright
twitter: @thecoda
"My point today is that, if we wish to count lines of code, we should not regard them as "lines produced" but as "lines spent": the current conventional wisdom is so foolish as to book that count on the wrong side of the ledger" ~ Dijkstra
packaging will initially fail when it tries to build the examples before the plugin jar is output. Running it a second time will work just fine.
On 5 April 2011 18:17, Roland Kuhn <google@rkuhn.info> wrote:
Hi Kevin,
this looks truly awesome (and I don’t care much about the restriction, because delegating an interface is the whole point, right?).
On Apr 5, 2011, at 16:30 , Kevin Wright wrote:I now have a (slightly restricted) version of the long awaited autoproxy plugin passing the first few basic tests.Okay, here it goes:
The jar isn't yet formally published anywhere, but the GitHub project can be found here: https://github.com/kevinwright/Autoproxy-Lite (Requires SBT 0.7.6.RC0 and targets Scala 2.9.0.RC1)
For anyone who likes like on the bleeding edge, please feel free to try it out and send me all your bug reports :)
How do I get started? I cloned, ran "sbt shell" and "doc", which seemed to compile all the crucial stuff and failed on the Simple Example (plugin not found). I tried "deliver", which complained about unspecified repo, "deliver-local" then downloaded quite some stuff, but in the end plugin/deliver-local could not download scala-library.jar(src). What next?
Regards,
Roland
--
Kevin Wright
gtalk / msn : kev.lee.wright@gmail.com kev.lee.wright@gmail.commail: kevin.wright@scalatechnology.com
vibe / skype: kev.lee.wrightquora: http://www.quora.com/Kevin-Wright
twitter: @thecoda
"My point today is that, if we wish to count lines of code, we should not regard them as "lines produced" but as "lines spent": the current conventional wisdom is so foolish as to book that count on the wrong side of the ledger" ~ Dijkstra
Wed, 2011-04-06, 16:17
#3
Re: Announcing autoproxy-lite
On Tue, Apr 5, 2011 at 7:30 AM, Kevin Wright <kev.lee.wright@gmail.com> wrote:
Hi Kevin,
Just curious, how does proxying work in conjunction with class/trait linearization? Are the rules defined/finalized and if so, is there a spec that explains the semantics?
alex
I now have a (slightly restricted) version of the long awaited autoproxy plugin passing the first few basic tests.
The jar isn't yet formally published anywhere, but the GitHub project can be found here: https://github.com/kevinwright/Autoproxy-Lite (Requires SBT 0.7.6.RC0 and targets Scala 2.9.0.RC1)
For anyone who likes like on the bleeding edge, please feel free to try it out and send me all your bug reports :)
Hi Kevin,
Just curious, how does proxying work in conjunction with class/trait linearization? Are the rules defined/finalized and if so, is there a spec that explains the semantics?
alex
Wed, 2011-04-06, 16:27
#4
Re: Announcing autoproxy-lite
On 6 April 2011 15:58, Alex Boisvert <alex.boisvert@gmail.com> wrote:
On Tue, Apr 5, 2011 at 7:30 AM, Kevin Wright <kev.lee.wright@gmail.com> wrote:I now have a (slightly restricted) version of the long awaited autoproxy plugin passing the first few basic tests.
The jar isn't yet formally published anywhere, but the GitHub project can be found here: https://github.com/kevinwright/Autoproxy-Lite (Requires SBT 0.7.6.RC0 and targets Scala 2.9.0.RC1)
For anyone who likes like on the bleeding edge, please feel free to try it out and send me all your bug reports :)
Hi Kevin,
Just curious, how does proxying work in conjunction with class/trait linearization? Are the rules defined/finalized and if so, is there a spec that explains the semantics?
No magic here, it's exactly as though you'd written the delegates by hand. As per the example:
trait SomeClass {
def theString: String
def theInt: Int
}
class DynamicMixin(@proxy instance: SomeClass) extends SomeClass {
override def toString = "theString=" + theString + ", theInt=" + theInt
}
becomes: trait SomeClass {
def theString: String
def theInt: Int
}
class DynamicMixin(@proxy instance: SomeClass) extends SomeClass {
override def toString = "theString=" + theString + ", theInt=" + theInt
def theString = instance.theString
def theInt = instance.theInt
}
alex
--
Kevin Wright
gtalk / msn : kev.lee.wright@gmail.comkev.lee.wright@gmail.commail: kevin.wright@scalatechnology.com
vibe / skype: kev.lee.wrightquora: http://www.quora.com/Kevin-Wright
twitter: @thecoda
"My point today is that, if we wish to count lines of code, we should not regard them as "lines produced" but as "lines spent": the current conventional wisdom is so foolish as to book that count on the wrong side of the ledger" ~ Dijkstra
Wed, 2011-04-06, 18:47
#5
Re: Announcing autoproxy-lite
On Wed, Apr 6, 2011 at 8:04 AM, Kevin Wright <kev.lee.wright@gmail.com> wrote:
Ok, more precisely, what happens in the face of overlapping methods?
trait Foo { def x = 1 }
trait Bar { def x = 2}
class FooBar(@proxy foo: Foo) extends Foo with Bar class BarFoo(@proxy foo: Foo) extends Bar with Foo
new FooBar.x // => 2?new BarFoo.x // => 1?
alex
On 6 April 2011 15:58, Alex Boisvert <alex.boisvert@gmail.com> wrote:
On Tue, Apr 5, 2011 at 7:30 AM, Kevin Wright <kev.lee.wright@gmail.com> wrote:I now have a (slightly restricted) version of the long awaited autoproxy plugin passing the first few basic tests.
The jar isn't yet formally published anywhere, but the GitHub project can be found here: https://github.com/kevinwright/Autoproxy-Lite (Requires SBT 0.7.6.RC0 and targets Scala 2.9.0.RC1)
For anyone who likes like on the bleeding edge, please feel free to try it out and send me all your bug reports :)
Hi Kevin,
Just curious, how does proxying work in conjunction with class/trait linearization? Are the rules defined/finalized and if so, is there a spec that explains the semantics?
No magic here, it's exactly as though you'd written the delegates by hand. As per the example:becomes:trait SomeClass { def theString: String def theInt: Int } class DynamicMixin(@proxy instance: SomeClass) extends SomeClass { override def toString = "theString=" + theString + ", theInt=" + theInt }
trait SomeClass { def theString: String def theInt: Int } class DynamicMixin(@proxy instance: SomeClass) extends SomeClass { override def toString = "theString=" + theString + ", theInt=" + theInt def theString = instance.theString def theInt = instance.theInt }
Ok, more precisely, what happens in the face of overlapping methods?
trait Foo { def x = 1 }
trait Bar { def x = 2}
class FooBar(@proxy foo: Foo) extends Foo with Bar class BarFoo(@proxy foo: Foo) extends Bar with Foo
new FooBar.x // => 2?new BarFoo.x // => 1?
alex
Wed, 2011-04-06, 18:47
#6
Re: Announcing autoproxy-lite
On Wed, Apr 6, 2011 at 10:39 AM, Alex Boisvert <alex.boisvert@gmail.com> wrote:
Sorry, bad example/question since you'd need to explicitly override to disambiguate.
Assume instead:
trait Foo { def x: Int}
new FooBar().x // invokes Bar.x or foo.x ?new BarFoo().x // invokes Bar.x or foo.x ?
See what I mean?
alex
On Wed, Apr 6, 2011 at 8:04 AM, Kevin Wright <kev.lee.wright@gmail.com> wrote:
On 6 April 2011 15:58, Alex Boisvert <alex.boisvert@gmail.com> wrote:
On Tue, Apr 5, 2011 at 7:30 AM, Kevin Wright <kev.lee.wright@gmail.com> wrote:I now have a (slightly restricted) version of the long awaited autoproxy plugin passing the first few basic tests.
The jar isn't yet formally published anywhere, but the GitHub project can be found here: https://github.com/kevinwright/Autoproxy-Lite (Requires SBT 0.7.6.RC0 and targets Scala 2.9.0.RC1)
For anyone who likes like on the bleeding edge, please feel free to try it out and send me all your bug reports :)
Hi Kevin,
Just curious, how does proxying work in conjunction with class/trait linearization? Are the rules defined/finalized and if so, is there a spec that explains the semantics?
No magic here, it's exactly as though you'd written the delegates by hand. As per the example:becomes:trait SomeClass { def theString: String def theInt: Int } class DynamicMixin(@proxy instance: SomeClass) extends SomeClass { override def toString = "theString=" + theString + ", theInt=" + theInt }
trait SomeClass { def theString: String def theInt: Int } class DynamicMixin(@proxy instance: SomeClass) extends SomeClass { override def toString = "theString=" + theString + ", theInt=" + theInt def theString = instance.theString def theInt = instance.theInt }
Ok, more precisely, what happens in the face of overlapping methods?
trait Foo { def x = 1 }
trait Bar { def x = 2}
class FooBar(@proxy foo: Foo) extends Foo with Bar class BarFoo(@proxy foo: Foo) extends Bar with Foo
new FooBar.x // => 2?new BarFoo.x // => 1?
Sorry, bad example/question since you'd need to explicitly override to disambiguate.
Assume instead:
trait Foo { def x: Int}
new FooBar().x // invokes Bar.x or foo.x ?new BarFoo().x // invokes Bar.x or foo.x ?
See what I mean?
alex
Wed, 2011-04-06, 19:47
#7
Re: Announcing autoproxy-lite
On Apr 6, 2011, at 19:45 , Alex Boisvert wrote:
I am also researching the ways of this plugin, and the following transcript might shed some light:
scala> trait Foo { def x : Int }defined trait Foo
scala> trait Bar { def x = 2 }defined trait Bar
scala> object F extends Foo { val x = 1 }defined module F
scala> class FooBar(@proxy foo: Foo) extends Foo with Bardefined class FooBar
scala> class BarFoo(@proxy foo: Foo) extends Bar with Foodefined class BarFoo
scala> new FooBar(F).xres0: Int = 1
scala> new BarFoo(F).xres1: Int = 1
scala> :javap -c FooBarCompiled from "<console>"public class FooBar extends java.lang.Object implements Foo,Bar,scala.ScalaObject{public int x(); Code: 0: aload_0 1: getfield #12; //Field foo:LFoo; 4: invokeinterface #16, 1; //InterfaceMethod Foo.x:()I 9: ireturn
public FooBar(Foo); Code: 0: aload_0 1: aload_1 2: putfield #12; //Field foo:LFoo; 5: aload_0 6: invokespecial #23; //Method java/lang/Object."<init>":()V 9: aload_0 10: invokestatic #29; //Method Bar$class.$init$:(LBar;)V 13: return
}
scala> :javap -c BarFooCompiled from "<console>"public class BarFoo extends java.lang.Object implements Bar,Foo,scala.ScalaObject{public int x(); Code: 0: aload_0 1: getfield #12; //Field foo:LFoo; 4: invokeinterface #16, 1; //InterfaceMethod Foo.x:()I 9: ireturn
public BarFoo(Foo); Code: 0: aload_0 1: aload_1 2: putfield #12; //Field foo:LFoo; 5: aload_0 6: invokespecial #23; //Method java/lang/Object."<init>":()V 9: aload_0 10: invokestatic #29; //Method Bar$class.$init$:(LBar;)V 13: return
}
scala> class B extends Bar { def x = 3 }<console>:9: error: overriding method x in trait Bar of type => Int; method x needs `override' modifier class B extends Bar { def x = 3 } ^
scala> class C(@proxy foo:Foo) { def x = 12 }<console>:9: error: double definition:method x:=> Int andmethod x:=> Int at line 9have same type class C(@proxy foo:Foo) { def x = 12 }
===============================
So, to summarize, the @proxy desugars quite literally to the methods being defined in the containing class. If there is already such a method, the normal “double definition” error ensues, on the other hand the synthetic methods override methods from mixed in traits unconditionally.
From this I conclude that one desirable improvement would be to leave out generation if a method of the same signature already exists. This would allow calling e.g. super.x in the above case.
Considering the shadowing of inherited methods, it would be nice if a warning could be emitted, possibly suppressible by annotating the @proxy annotation.
Regards,
Roland
PS: I LOVE :javap!!!D
On Wed, Apr 6, 2011 at 10:39 AM, Alex Boisvert <alex.boisvert@gmail.com> wrote:On Wed, Apr 6, 2011 at 8:04 AM, Kevin Wright <kev.lee.wright@gmail.com> wrote:
No magic here, it's exactly as though you'd written the delegates by hand. As per the example:becomes:trait SomeClass { def theString: String def theInt: Int } class DynamicMixin(@proxy instance: SomeClass) extends SomeClass { override def toString = "theString=" + theString + ", theInt=" + theInt }
trait SomeClass { def theString: String def theInt: Int } class DynamicMixin(@proxy instance: SomeClass) extends SomeClass { override def toString = "theString=" + theString + ", theInt=" + theInt def theString = instance.theString def theInt = instance.theInt }
Ok, more precisely, what happens in the face of overlapping methods?
trait Foo { def x = 1 }
trait Bar { def x = 2}
class FooBar(@proxy foo: Foo) extends Foo with Bar class BarFoo(@proxy foo: Foo) extends Bar with Foo
new FooBar.x // => 2?new BarFoo.x // => 1?
Sorry, bad example/question since you'd need to explicitly override to disambiguate.
Assume instead:
trait Foo { def x: Int}
new FooBar().x // invokes Bar.x or foo.x ?new BarFoo().x // invokes Bar.x or foo.x ?
See what I mean?
I am also researching the ways of this plugin, and the following transcript might shed some light:
scala> trait Foo { def x : Int }defined trait Foo
scala> trait Bar { def x = 2 }defined trait Bar
scala> object F extends Foo { val x = 1 }defined module F
scala> class FooBar(@proxy foo: Foo) extends Foo with Bardefined class FooBar
scala> class BarFoo(@proxy foo: Foo) extends Bar with Foodefined class BarFoo
scala> new FooBar(F).xres0: Int = 1
scala> new BarFoo(F).xres1: Int = 1
scala> :javap -c FooBarCompiled from "<console>"public class FooBar extends java.lang.Object implements Foo,Bar,scala.ScalaObject{public int x(); Code: 0: aload_0 1: getfield #12; //Field foo:LFoo; 4: invokeinterface #16, 1; //InterfaceMethod Foo.x:()I 9: ireturn
public FooBar(Foo); Code: 0: aload_0 1: aload_1 2: putfield #12; //Field foo:LFoo; 5: aload_0 6: invokespecial #23; //Method java/lang/Object."<init>":()V 9: aload_0 10: invokestatic #29; //Method Bar$class.$init$:(LBar;)V 13: return
}
scala> :javap -c BarFooCompiled from "<console>"public class BarFoo extends java.lang.Object implements Bar,Foo,scala.ScalaObject{public int x(); Code: 0: aload_0 1: getfield #12; //Field foo:LFoo; 4: invokeinterface #16, 1; //InterfaceMethod Foo.x:()I 9: ireturn
public BarFoo(Foo); Code: 0: aload_0 1: aload_1 2: putfield #12; //Field foo:LFoo; 5: aload_0 6: invokespecial #23; //Method java/lang/Object."<init>":()V 9: aload_0 10: invokestatic #29; //Method Bar$class.$init$:(LBar;)V 13: return
}
scala> class B extends Bar { def x = 3 }<console>:9: error: overriding method x in trait Bar of type => Int; method x needs `override' modifier class B extends Bar { def x = 3 } ^
scala> class C(@proxy foo:Foo) { def x = 12 }<console>:9: error: double definition:method x:=> Int andmethod x:=> Int at line 9have same type class C(@proxy foo:Foo) { def x = 12 }
===============================
So, to summarize, the @proxy desugars quite literally to the methods being defined in the containing class. If there is already such a method, the normal “double definition” error ensues, on the other hand the synthetic methods override methods from mixed in traits unconditionally.
From this I conclude that one desirable improvement would be to leave out generation if a method of the same signature already exists. This would allow calling e.g. super.x in the above case.
Considering the shadowing of inherited methods, it would be nice if a warning could be emitted, possibly suppressible by annotating the @proxy annotation.
Regards,
Roland
PS: I LOVE :javap!!!D
Wed, 2011-04-06, 21:07
#8
Re: Announcing autoproxy-lite
On Wed, Apr 6, 2011 at 11:44 AM, Roland Kuhn <google@rkuhn.info> wrote:
Thanks Roland, you answered my question nicely.
alex
So, to summarize, the @proxy desugars quite literally to the methods being defined in the containing class. If there is already such a method, the normal “double definition” error ensues, on the other hand the synthetic methods override methods from mixed in traits unconditionally.
From this I conclude that one desirable improvement would be to leave out generation if a method of the same signature already exists. This would allow calling e.g. super.x in the above case.
Considering the shadowing of inherited methods, it would be nice if a warning could be emitted, possibly suppressible by annotating the @proxy annotation.
Thanks Roland, you answered my question nicely.
alex
this looks truly awesome (and I don’t care much about the restriction, because delegating an interface is the whole point, right?).
On Apr 5, 2011, at 16:30 , Kevin Wright wrote:
Okay, here it goes:
How do I get started? I cloned, ran "sbt shell" and "doc", which seemed to compile all the crucial stuff and failed on the Simple Example (plugin not found). I tried "deliver", which complained about unspecified repo, "deliver-local" then downloaded quite some stuff, but in the end plugin/deliver-local could not download scala-library.jar(src). What next?
Regards,
Roland