- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Re: Announcing autoproxy-lite
Tue, 2011-04-05, 20:25
On 5 April 2011 20:19, Roland Kuhn <google@rkuhn.info> wrote:
Okay, got it working. I’ve been playing around with rather simple stuff in the REPL and it looks good! I assume that there is a nasty reason why it does not work on constructor arguments which are declared as fields?
class Test(@proxy var dg : Bippy) extends Bippy
error: class Test needs to be abstract, since method bippy in trait Bippy of type (i: Int)String is not defined
How is Bippy defined? I suspect it contains a val, which is flagged STABLE and so can't be changed post-construction in any subclass of Bippy. However, by making dg mutable you break that contract - It's on my todo list to add an error message for this exact situation.
On Apr 5, 2011, at 19:43 , Kevin Wright wrote:"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: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
--
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, 01:47
#2
Re: Announcing autoproxy-lite
The workaround, for now, is to annotate the annotation - specifying the target:
class BippyTest(@(proxy @field) var dg : Bippy) extends Bippy
I'll fix things in a commit (likely tomorrow) so you don't have to do this.
On 5 April 2011 20:49, 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
class BippyTest(@(proxy @field) var dg : Bippy) extends Bippy
I'll fix things in a commit (likely tomorrow) so you don't have to do this.
On 5 April 2011 20:49, Roland Kuhn <google@rkuhn.info> wrote:
On Apr 5, 2011, at 21:25 , Kevin Wright wrote:On 5 April 2011 20:19, Roland Kuhn <google@rkuhn.info> wrote:While that was definitely something I did not think about (thanks) it is not the problem here:
Okay, got it working. I’ve been playing around with rather simple stuff in the REPL and it looks good! I assume that there is a nasty reason why it does not work on constructor arguments which are declared as fields?
class Test(@proxy var dg : Bippy) extends Bippy
error: class Test needs to be abstract, since method bippy in trait Bippy of type (i: Int)String is not defined
How is Bippy defined? I suspect it contains a val, which is flagged STABLE and so can't be changed post-construction in any subclass of Bippy. However, by making dg mutable you break that contract - It's on my todo list to add an error message for this exact situation.
trait Bippy { def bippy(i : Int) : String }
Plus, the same error occurs when changing "var" to "val".
--
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, 02:07
#3
Re: Announcing autoproxy-lite
Okay, all fixed now :)
On 6 April 2011 01:45, Kevin Wright <kev.lee.wright@gmail.com> wrote:
--
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
On 6 April 2011 01:45, Kevin Wright <kev.lee.wright@gmail.com> wrote:
The workaround, for now, is to annotate the annotation - specifying the target:
class BippyTest(@(proxy @field) var dg : Bippy) extends Bippy
I'll fix things in a commit (likely tomorrow) so you don't have to do this.
On 5 April 2011 20:49, Roland Kuhn <google@rkuhn.info> wrote:
On Apr 5, 2011, at 21:25 , Kevin Wright wrote:On 5 April 2011 20:19, Roland Kuhn <google@rkuhn.info> wrote:While that was definitely something I did not think about (thanks) it is not the problem here:
Okay, got it working. I’ve been playing around with rather simple stuff in the REPL and it looks good! I assume that there is a nasty reason why it does not work on constructor arguments which are declared as fields?
class Test(@proxy var dg : Bippy) extends Bippy
error: class Test needs to be abstract, since method bippy in trait Bippy of type (i: Int)String is not defined
How is Bippy defined? I suspect it contains a val, which is flagged STABLE and so can't be changed post-construction in any subclass of Bippy. However, by making dg mutable you break that contract - It's on my todo list to add an error message for this exact situation.
trait Bippy { def bippy(i : Int) : String }
Plus, the same error occurs when changing "var" to "val".
--
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
--
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, 08:07
#4
Re: Announcing autoproxy-lite
Yep, all works now. I also tried adding @volatile (for which I imagine having a use case), works like a charm.
Now to business: when do you think this is production-ready? What are the known deficiencies? I would love to see this in Scala proper, in fact that was the only thing I felt missing after having been given a lunch tour across Scala-land two years back (with the “aaah”s and “oooh”s still echoing in my brain ;-) ).
Concerning having to explicitly extend the interface, I think that is actually a good thing, and you won’t even notice it much:
trait Bippy { def bippy(i : Int) : String }trait Bappa { def bippy(i : Int) : String; def bappa(o : AnyRef) : Unit }class Test(@proxy var dg : Bippy) extends Bappa { def bappa(o : AnyRef) {} }
works just fine, no inheritance hierarchies needed for anything. I have the feeling I should call this “duck composition”. One more degree of freedom in designing the solution space!
What do you all think?
On Apr 6, 2011, at 03:02 , Kevin Wright wrote:
Now to business: when do you think this is production-ready? What are the known deficiencies? I would love to see this in Scala proper, in fact that was the only thing I felt missing after having been given a lunch tour across Scala-land two years back (with the “aaah”s and “oooh”s still echoing in my brain ;-) ).
Concerning having to explicitly extend the interface, I think that is actually a good thing, and you won’t even notice it much:
trait Bippy { def bippy(i : Int) : String }trait Bappa { def bippy(i : Int) : String; def bappa(o : AnyRef) : Unit }class Test(@proxy var dg : Bippy) extends Bappa { def bappa(o : AnyRef) {} }
works just fine, no inheritance hierarchies needed for anything. I have the feeling I should call this “duck composition”. One more degree of freedom in designing the solution space!
What do you all think?
On Apr 6, 2011, at 03:02 , Kevin Wright wrote:
Okay, all fixed now :)
On 6 April 2011 01:45, Kevin Wright <kev.lee.wright@gmail.com> wrote:The workaround, for now, is to annotate the annotation - specifying the target:
class BippyTest(@(proxy @field) var dg : Bippy) extends Bippy
I'll fix things in a commit (likely tomorrow) so you don't have to do this.
On 5 April 2011 20:49, Roland Kuhn <google@rkuhn.info> wrote:
On Apr 5, 2011, at 21:25 , Kevin Wright wrote:On 5 April 2011 20:19, Roland Kuhn <google@rkuhn.info> wrote:While that was definitely something I did not think about (thanks) it is not the problem here:
Okay, got it working. I’ve been playing around with rather simple stuff in the REPL and it looks good! I assume that there is a nasty reason why it does not work on constructor arguments which are declared as fields?
class Test(@proxy var dg : Bippy) extends Bippy
error: class Test needs to be abstract, since method bippy in trait Bippy of type (i: Int)String is not defined
How is Bippy defined? I suspect it contains a val, which is flagged STABLE and so can't be changed post-construction in any subclass of Bippy. However, by making dg mutable you break that contract - It's on my todo list to add an error message for this exact situation.
trait Bippy { def bippy(i : Int) : String }
Plus, the same error occurs when changing "var" to "val".
--
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
--
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, 20:57
#5
Re: Announcing autoproxy-lite
On 6 April 2011 19:44, Roland Kuhn <google@rkuhn.info> wrote:
>
> On Apr 6, 2011, at 19:45 , Alex Boisvert wrote:
>
>> 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:
>>>>
>>>>
>>>> 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
>>>> }
>>>
>>>
>>> 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 Bar
> defined class FooBar
>
> scala> class BarFoo(@proxy foo: Foo) extends Bar with Foo
> defined class BarFoo
>
> scala> new FooBar(F).x
> res0: Int = 1
>
> scala> new BarFoo(F).x
> res1: Int = 1
>
> scala> :javap -c FooBar
> Compiled 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 BarFoo
> Compiled 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 and
> method x:=> Int at line 9
> have 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.
>
Okay, that's a regression, it shouldn't be synthesising methods if you've already explicitly defined them. Expect a bug fix shortly.
> Considering the shadowing of inherited methods, it would be nice if a warning could be emitted, possibly suppressible by annotating the @proxy annotation.
>
I'll try a full write up of the logic soon. As you might expect, it uses a certain amount of cleverness in order to appear intuitive.
> Regards,
>
> Roland
>
> PS: I LOVE :javap!!!D
Try -Xprint:generatesynthetics, it's my personal weapon of choice in these situations.
Wed, 2011-04-06, 21:57
#6
Re: Announcing autoproxy-lite
> 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.
>Okay, that's a regression, it shouldn't be synthesising methods if you've already explicitly defined them. Expect a bug fix shortly.
and.... it's done.
--
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, 22:47
#7
Re: Announcing autoproxy-lite
On Apr 6, 2011, at 22:51 , Kevin Wright wrote:
Verified! (Man, you’re quick :-) )> 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.
>Okay, that's a regression, it shouldn't be synthesising methods if you've already explicitly defined them. Expect a bug fix shortly.
and.... it's done.
While testing, I stumbled across something worth keeping at the back of your mind:
scala> trait Foo { def x : Int }defined trait Foo
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 } ^
The explicit interface should not be needed if my class’ code does not depend on it (verified that in different case), but the error looks strange …
Regards,
Roland
Wed, 2011-04-06, 23:08
#8
Re: Announcing autoproxy-lite
Wed, 2011-04-06, 23:17
#9
Re: Announcing autoproxy-lite
On 6 April 2011 22:34, Roland Kuhn <google@rkuhn.info> wrote:
On Apr 6, 2011, at 22:51 , Kevin Wright wrote:Verified! (Man, you’re quick :-) )> 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.
>Okay, that's a regression, it shouldn't be synthesising methods if you've already explicitly defined them. Expect a bug fix shortly.
and.... it's done.
While testing, I stumbled across something worth keeping at the back of your mind:
scala> trait Foo { def x : Int }defined trait Foo
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 } ^
The explicit interface should not be needed if my class’ code does not depend on it (verified that in different case), but the error looks strange …
Strictly speaking, the only requirement is that the code successfully type-checks before generation of the delegates. The easiest way to guarantee this is to also inherit from the proxied type, though it's certainly not the only one.
For example, a dedicated abstract trait could be used as an interface:
trait Interface { def x: String def y: Int}
trait Concrete extends Interface { val x = "Hello World" val y = 42 }
class TheClass(@proxy underlying: Concrete) extends Interface
I also suspect that `Dynamic` could help out here, but have yet to experiment.
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
Thu, 2011-04-07, 06:47
#10
Re: Announcing autoproxy-lite
On Apr 6, 2011, at 23:48, Kevin Wright <kev.lee.wright@gmail.com> wrote:
On 6 April 2011 22:34, Roland Kuhn < (google [at] rkuhn [dot] info> wrote:Understood. As I said, this will not be such a problem in my opinion because the delegating methods will be implementing some interface anyway.
On Apr 6, 2011, at 22:51 , Kevin Wright wrote:Verified! (Man, you’re quick :-) )> 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.
>Okay, that's a regression, it shouldn't be synthesising methods if you've already explicitly defined them. Expect a bug fix shortly.
and.... it's done.
While testing, I stumbled across something worth keeping at the back of your mind:
scala> trait Foo { def x : Int }defined trait Foo
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 } ^
The explicit interface should not be needed if my class’ code does not depend on it (verified that in different case), but the error looks strange …
Strictly speaking, the only requirement is that the code successfully type-checks before generation of the delegates. The easiest way to guarantee this is to also inherit from the proxied type, though it's certainly not the only one.
For example, a dedicated abstract trait could be used as an interface:trait Interface { def x: String def y: Int}
trait Concrete extends Interface { val x = "Hello World" val y = 42 }
class TheClass(@proxy underlying: Concrete) extends Interface
I also suspect that `Dynamic` could help out here, but have yet to experiment.
But this does not explain why your "double declaration" fix does not work without the interface.
Regards,
Roland
Thu, 2011-04-07, 11:27
#11
Re: Announcing autoproxy-lite
On 7 April 2011 06:42, Roland Kuhn <google@rkuhn.info> wrote:
On Apr 6, 2011, at 23:48, Kevin Wright <kev.lee.wright@gmail.com> wrote:
On 6 April 2011 22:34, Roland Kuhn <google@rkuhn.infogoogle@rkuhn.info> wrote:Understood. As I said, this will not be such a problem in my opinion because the delegating methods will be implementing some interface anyway.
On Apr 6, 2011, at 22:51 , Kevin Wright wrote:Verified! (Man, you’re quick :-) )> 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.
>Okay, that's a regression, it shouldn't be synthesising methods if you've already explicitly defined them. Expect a bug fix shortly.
and.... it's done.
While testing, I stumbled across something worth keeping at the back of your mind:
scala> trait Foo { def x : Int }defined trait Foo
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 } ^
The explicit interface should not be needed if my class’ code does not depend on it (verified that in different case), but the error looks strange …
Strictly speaking, the only requirement is that the code successfully type-checks before generation of the delegates. The easiest way to guarantee this is to also inherit from the proxied type, though it's certainly not the only one.
For example, a dedicated abstract trait could be used as an interface:trait Interface { def x: String def y: Int}
trait Concrete extends Interface { val x = "Hello World" val y = 42 }
class TheClass(@proxy underlying: Concrete) extends Interface
I also suspect that `Dynamic` could help out here, but have yet to experiment.
But this does not explain why your "double declaration" fix does not work without the interface.
curious... I have a couple of ideas though :)
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
Thu, 2011-04-07, 17:07
#12
Re: Announcing autoproxy-lite
On 7 Apr 2011 11:09, "Kevin Wright" <kev.lee.wright@gmail.com> wrote:
>
>
>
> On 7 April 2011 06:42, Roland Kuhn <google@rkuhn.info> wrote:
>>
>>
>> On Apr 6, 2011, at 23:48, Kevin Wright <kev.lee.wright@gmail.com> wrote:
>>
>>> On 6 April 2011 22:34, Roland Kuhn <google@rkuhn.info> wrote:
>>>>
>>>>
>>>> On Apr 6, 2011, at 22:51 , Kevin Wright wrote:
>>>>
>>>>>> > 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.
>>>>>> >
>>>>>>
>>>>>> Okay, that's a regression, it shouldn't be synthesising methods if you've already explicitly defined them. Expect a bug fix shortly.
>>>>>
>>>>>
>>>>> and.... it's done.
>>>>>
>>>> Verified! (Man, you’re quick :-) )
>>>>
>>>> While testing, I stumbled across something worth keeping at the back of your mind:
>>>>
>>>> scala> trait Foo { def x : Int }
>>>> defined trait Foo
>>>>
>>>> scala> class C(@proxy foo:Foo) { def x = 12 }
>>>> <console>:9: error: double definition:
>>>> method x:=> Int and
>>>> method x:=> Int at line 9
>>>> have same type
>>>> class C(@proxy foo:Foo) { def x = 12 }
>>>> ^
>>>>
>>>> The explicit interface should not be needed if my class’ code does not depend on it (verified that in different case), but the error looks strange …
>>>>
>>>
>>> Strictly speaking, the only requirement is that the code successfully type-checks before generation of the delegates. The easiest way to guarantee this is to also inherit from the proxied type, though it's certainly not the only one.
>>>
>>> For example, a dedicated abstract trait could be used as an interface:
>>>
>>>> trait Interface {
>>>> def x: String
>>>> def y: Int
>>>> }
>>>>
>>>> trait Concrete extends Interface {
>>>> val x = "Hello World"
>>>> val y = 42
>>>> }
>>>>
>>>> class TheClass(@proxy underlying: Concrete) extends Interface
>>>
>>>
>>> I also suspect that `Dynamic` could help out here, but have yet to experiment.
>>>
>>
>> Understood. As I said, this will not be such a problem in my opinion because the delegating methods will be implementing some interface anyway.
>>
>> But this does not explain why your "double declaration" fix does not work without the interface.
>>
>
> curious... I have a couple of ideas though :)
>
I have a fix for this, the final push to github awaits something a bit more reliable than 3g in rural UK though...
>>
>> Regards,
>>
>> Roland
>
>
>
>
> --
> Kevin Wright
>
> gtalk / msn : kev.lee.wright@gmail.com
> mail: kevin.wright@scalatechnology.com
> vibe / skype: kev.lee.wright
> quora: 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
>
On Apr 5, 2011, at 21:25 , Kevin Wright wrote:
While that was definitely something I did not think about (thanks) it is not the problem here:
trait Bippy { def bippy(i : Int) : String}
Plus, the same error occurs when changing "var" to "val".