|
View:
New views
16 Messages
—
Rating Filter:
Alert me
|
|
|
[scala] Constructor parameters for traitsHello, List.
I know that traits can not have constructor parameters, however I have not been able to find out much about the rationale behind this restriction; my google-fu fails me and the SLS is quiet on it (or, maybe, I just don't know where to look for it). For this scala code > trait A { > System.out.println("Hello, World!") > } > > class AImpl extends A scalac will generate (something closely resembling) the following pseudo-Java: > public interface A {} > > public class A$class { > public static void $init$(A $this) { > System.out.println("Hello, World!"); > } > } > > public class AImpl implements A { > public A() { > A$class.$init$(this); > } > } should also be able to accept constructor parameters for traits: > trait A(message: String) { > System.out.println(message) > } and just tack on the arguments to the $init$ method of the trait's implementation class: > public interface A {} > > public class A$class { > public static void $init$(A $this, String message) { > System.out.println(message); > } > } Is this a bad idea? Cheers, Sébastien |
|
|
Re: [scala] Constructor parameters for traitsI think there's been some discussion of lifting the restriction. I don't believe it has any particular reasoning for it except that it would look scarily like full blown multiple inheritance.
|
|
|
Re: [scala] Constructor parameters for traitsThe reason why Scala doesn't have them right know is that no one has
worked out reasonable semantics for them yet: order of evaluation, what happens in the case of diamond inheritance and so on. We are currently working on adding them though. Ingo Sebastien Braun wrote: > Hello, List. > > I know that traits can not have constructor parameters, however I have not > been able to find out much about the rationale behind this restriction; my > google-fu fails me and the SLS is quiet on it (or, maybe, I just don't know > where to look for it). > > For this scala code > >> trait A { >> System.out.println("Hello, World!") >> } >> >> class AImpl extends A > > scalac will generate (something closely resembling) the following pseudo-Java: > >> public interface A {} >> >> public class A$class { >> public static void $init$(A $this) { >> System.out.println("Hello, World!"); >> } >> } >> >> public class AImpl implements A { >> public A() { >> A$class.$init$(this); >> } >> } > > So, intuitively (and perhaps naïvely...), it seems to me that the compiler > should also be able to accept constructor parameters for traits: > >> trait A(message: String) { >> System.out.println(message) >> } > > and just tack on the arguments to the $init$ method of the trait's > implementation class: > >> public interface A {} >> >> public class A$class { >> public static void $init$(A $this, String message) { >> System.out.println(message); >> } >> } > > Is this a bad idea? > > Cheers, > > Sébastien |
|
|
Re: [scala] Constructor parameters for traitsDiamond inheritance creates extra complexity. Here's one example
trait Base(val msg : String} trait Sub1 extends Base("hello") trait Sub2 extends Base("goodbye") Object Test extends Sub1 with Sub2 println(Test.msg) // hello? goodbye? error? There are ways for a language to let you resolve diamond inheritance. But it does complicate things. On Tue, Dec 2, 2008 at 9:17 AM, Sebastien Braun <sebb@...> wrote: Hello, List. |
|
|
Re: [scala] Constructor parameters for traitsBut what about this?:
trait Base{ val msg: String } trait Sub1 extends Base{ override val msg = "hello" } trait Sub2 extends Base{ override val msg = "goodbye" } Object Test extends Sub1 with Sub2 The above code works fine. Why not apply the same rules to solve diamond inheritance? - Andrés 2008/12/2 James Iry <jamesiry@...>: > Diamond inheritance creates extra complexity. Here's one example > > trait Base(val msg : String} > trait Sub1 extends Base("hello") > trait Sub2 extends Base("goodbye") > Object Test extends Sub1 with Sub2 > println(Test.msg) // hello? goodbye? error? > > There are ways for a language to let you resolve diamond inheritance. But > it does complicate things. > > On Tue, Dec 2, 2008 at 9:17 AM, Sebastien Braun <sebb@...> > wrote: >> >> Hello, List. >> >> I know that traits can not have constructor parameters, however I have not >> been able to find out much about the rationale behind this restriction; my >> google-fu fails me and the SLS is quiet on it (or, maybe, I just don't >> know >> where to look for it). >> >> For this scala code >> >> > trait A { >> > System.out.println("Hello, World!") >> > } >> > >> > class AImpl extends A >> >> scalac will generate (something closely resembling) the following >> pseudo-Java: >> >> > public interface A {} >> > >> > public class A$class { >> > public static void $init$(A $this) { >> > System.out.println("Hello, World!"); >> > } >> > } >> > >> > public class AImpl implements A { >> > public A() { >> > A$class.$init$(this); >> > } >> > } >> >> So, intuitively (and perhaps naïvely...), it seems to me that the compiler >> should also be able to accept constructor parameters for traits: >> >> > trait A(message: String) { >> > System.out.println(message) >> > } >> >> and just tack on the arguments to the $init$ method of the trait's >> implementation class: >> >> > public interface A {} >> > >> > public class A$class { >> > public static void $init$(A $this, String message) { >> > System.out.println(message); >> > } >> > } >> >> Is this a bad idea? >> >> Cheers, >> >> Sébastien > > |
|
|
Re: [scala] Constructor parameters for traitsOh, sorry, my code doesn't really works :-(
2008/12/2 Andrés Testi <andres.a.testi@...>: > But what about this?: > > trait Base{ val msg: String } > trait Sub1 extends Base{ override val msg = "hello" } > trait Sub2 extends Base{ override val msg = "goodbye" } > Object Test extends Sub1 with Sub2 > > The above code works fine. Why not apply the same rules to solve > diamond inheritance? > > - Andrés > > 2008/12/2 James Iry <jamesiry@...>: >> Diamond inheritance creates extra complexity. Here's one example >> >> trait Base(val msg : String} >> trait Sub1 extends Base("hello") >> trait Sub2 extends Base("goodbye") >> Object Test extends Sub1 with Sub2 >> println(Test.msg) // hello? goodbye? error? >> >> There are ways for a language to let you resolve diamond inheritance. But >> it does complicate things. >> >> On Tue, Dec 2, 2008 at 9:17 AM, Sebastien Braun <sebb@...> >> wrote: >>> >>> Hello, List. >>> >>> I know that traits can not have constructor parameters, however I have not >>> been able to find out much about the rationale behind this restriction; my >>> google-fu fails me and the SLS is quiet on it (or, maybe, I just don't >>> know >>> where to look for it). >>> >>> For this scala code >>> >>> > trait A { >>> > System.out.println("Hello, World!") >>> > } >>> > >>> > class AImpl extends A >>> >>> scalac will generate (something closely resembling) the following >>> pseudo-Java: >>> >>> > public interface A {} >>> > >>> > public class A$class { >>> > public static void $init$(A $this) { >>> > System.out.println("Hello, World!"); >>> > } >>> > } >>> > >>> > public class AImpl implements A { >>> > public A() { >>> > A$class.$init$(this); >>> > } >>> > } >>> >>> So, intuitively (and perhaps naïvely...), it seems to me that the compiler >>> should also be able to accept constructor parameters for traits: >>> >>> > trait A(message: String) { >>> > System.out.println(message) >>> > } >>> >>> and just tack on the arguments to the $init$ method of the trait's >>> implementation class: >>> >>> > public interface A {} >>> > >>> > public class A$class { >>> > public static void $init$(A $this, String message) { >>> > System.out.println(message); >>> > } >>> > } >>> >>> Is this a bad idea? >>> >>> Cheers, >>> >>> Sébastien >> >> > |
|
|
Re: [scala] Constructor parameters for traitsBut my example is yet valid. The compiler refuses my code because msg
in Sub1 was overriding msg in Sub2. Why not apply the same compiler restrictions on trait constructors? - Andrés 2008/12/2 Andrés Testi <andres.a.testi@...>: > Oh, sorry, my code doesn't really works :-( > > 2008/12/2 Andrés Testi <andres.a.testi@...>: >> But what about this?: >> >> trait Base{ val msg: String } >> trait Sub1 extends Base{ override val msg = "hello" } >> trait Sub2 extends Base{ override val msg = "goodbye" } >> Object Test extends Sub1 with Sub2 >> >> The above code works fine. Why not apply the same rules to solve >> diamond inheritance? >> >> - Andrés >> >> 2008/12/2 James Iry <jamesiry@...>: >>> Diamond inheritance creates extra complexity. Here's one example >>> >>> trait Base(val msg : String} >>> trait Sub1 extends Base("hello") >>> trait Sub2 extends Base("goodbye") >>> Object Test extends Sub1 with Sub2 >>> println(Test.msg) // hello? goodbye? error? >>> >>> There are ways for a language to let you resolve diamond inheritance. But >>> it does complicate things. >>> >>> On Tue, Dec 2, 2008 at 9:17 AM, Sebastien Braun <sebb@...> >>> wrote: >>>> >>>> Hello, List. >>>> >>>> I know that traits can not have constructor parameters, however I have not >>>> been able to find out much about the rationale behind this restriction; my >>>> google-fu fails me and the SLS is quiet on it (or, maybe, I just don't >>>> know >>>> where to look for it). >>>> >>>> For this scala code >>>> >>>> > trait A { >>>> > System.out.println("Hello, World!") >>>> > } >>>> > >>>> > class AImpl extends A >>>> >>>> scalac will generate (something closely resembling) the following >>>> pseudo-Java: >>>> >>>> > public interface A {} >>>> > >>>> > public class A$class { >>>> > public static void $init$(A $this) { >>>> > System.out.println("Hello, World!"); >>>> > } >>>> > } >>>> > >>>> > public class AImpl implements A { >>>> > public A() { >>>> > A$class.$init$(this); >>>> > } >>>> > } >>>> >>>> So, intuitively (and perhaps naïvely...), it seems to me that the compiler >>>> should also be able to accept constructor parameters for traits: >>>> >>>> > trait A(message: String) { >>>> > System.out.println(message) >>>> > } >>>> >>>> and just tack on the arguments to the $init$ method of the trait's >>>> implementation class: >>>> >>>> > public interface A {} >>>> > >>>> > public class A$class { >>>> > public static void $init$(A $this, String message) { >>>> > System.out.println(message); >>>> > } >>>> > } >>>> >>>> Is this a bad idea? >>>> >>>> Cheers, >>>> >>>> Sébastien >>> >>> >> > |
|
|
Re: [scala] Constructor parameters for traitsI'm desperate for trait constructor arguments only because I need a Manifest for my trait's type argument (in order to include code whose behavior depends on the type). Something like:
trait Farm[A <: Animal](implicit m:Manifest[A]) { def foo(a:Animal) = if (m.erasure == a.getClass) bar1 else bar2 } Is there some other recommended work-around? Of course my true use-case is a bit more complicated. I'm stuck without a solution. -Andrew
|
|
|
Re: [scala] Constructor parameters for traitsOn Tue, Jun 30, 2009 at 2:57 PM, Andrew McCallum<mccallum@...> wrote:
> I'm desperate for trait constructor arguments only because I need a Manifest > for my trait's type argument (in order to include code whose behavior > depends on the type). Something like: > > trait Farm[A <: Animal](implicit m:Manifest[A]) { > def foo(a:Animal) = if (m.erasure == a.getClass) bar1 else bar2 > } > > Is there some other recommended work-around? Of course my true use-case is > a bit more complicated. I'm stuck without a solution. Couldn't you move the implicit parameter to the method? trait Farm[A <: Animal] { def foo(a:Animal)(implicit m:Manifest[A]) = if (m.erasure == a.getClass) bar1 else bar2 } Cheers, Miles -- Miles Sabin tel: +44 (0)7813 944 528 skype: milessabin http://www.chuusai.com/ http://twitter.com/milessabin |
|
|
Re: [scala] Constructor parameters for traitsDoesn't linearization help here ?
On Tue, Dec 2, 2008 at 8:58 PM, James Iry <jamesiry@...> wrote: Diamond inheritance creates extra complexity. Here's one example |
|
|
Re: [scala] Constructor parameters for traitsOn Tue, Jun 30, 2009 at 06:57:30AM -0700, Andrew McCallum wrote:
> I'm desperate for trait constructor arguments only because I need a > Manifest for my trait's type argument (in order to include code whose > behavior depends on the type). Something like: > > trait Farm[A <: Animal](implicit m:Manifest[A]) { > def foo(a:Animal) = if (m.erasure == a.getClass) bar1 else bar2 > } scala> trait Farm[A <: AnyRef] { def m(implicit man: reflect.Manifest[A]) = man } scala> (new Farm[String] {}).m res3: scala.reflect.Manifest[String] = java.lang.String scala> (new Farm[List[String]] {}).m res4: scala.reflect.Manifest[List[String]] = scala.collection.immutable.List[java.lang.String] (Not sure what those Strings are doing on the Farm, but anyway.) -- Paul Phillips | If this is raisin, make toast with it. Future Perfect | Empiricist | up hill, pi pals! |----------* http://www.improving.org/paulp/ *---------- |
|
|
Re: [scala] Constructor parameters for traitsThe one situation where I've wanted trait constructor arguments is for
a very similar use to the one he describes - I really wish I could do: trait Interval[T <% Ordered[T]] { ... } But, of course, view bounds are desugared to add implicit conversion function parameters to the methods that they annotate, and thus don't work in this kind of position. Is there a good way to provide such a trait? Kris On Tue, Jun 30, 2009 at 8:16 AM, Paul Phillips<paulp@...> wrote: > On Tue, Jun 30, 2009 at 06:57:30AM -0700, Andrew McCallum wrote: >> I'm desperate for trait constructor arguments only because I need a >> Manifest for my trait's type argument (in order to include code whose >> behavior depends on the type). Something like: >> >> trait Farm[A <: Animal](implicit m:Manifest[A]) { >> def foo(a:Animal) = if (m.erasure == a.getClass) bar1 else bar2 >> } > > scala> trait Farm[A <: AnyRef] { def m(implicit man: reflect.Manifest[A]) = man } > > scala> (new Farm[String] {}).m > res3: scala.reflect.Manifest[String] = java.lang.String > > scala> (new Farm[List[String]] {}).m > res4: scala.reflect.Manifest[List[String]] = scala.collection.immutable.List[java.lang.String] > > (Not sure what those Strings are doing on the Farm, but anyway.) > > -- > Paul Phillips | If this is raisin, make toast with it. > Future Perfect | > Empiricist | > up hill, pi pals! |----------* http://www.improving.org/paulp/ *---------- > |
|
|
Re: [scala] Constructor parameters for traitsPaul, Thank you for your input. This solution works if we know the type of the object when method "m" is being called, but unfortunately this isn't true in my use case. At its heart, I need a Manifest for a type argument inside the implementation of the trait... in a way that will allow me to place the objects conforming to the trait in a collection (among others that do not share precisely the same type arguments).
Perhaps the thread title "constructor parameters for traits" is the wrong one for me---I don't necessarily need a solution depending on a constructor. I just need a way to remember the non-erased type of the trait's type argument. A simple example demonstrating my needs is the following. Below "Restaurant1" and "Restaurant2" must be traits (not classes), because in my actual case it is getting mixed into another set of objects that vary in a different way. trait Nationality trait Italian extends Nationality trait Chinese extends Nationality trait Japanese extends Nationality trait Korean extends Nationality trait Restaurant { def feed(customer:Nationality) : String } trait Resaurant1[N1<:Nationality] extends Restaurant { def m1(implicit man: reflect.Manifest[N1]) = man def feed(customer:Nationality) = if (m.erasure == customer.getClass) "dish" else "sorry" } trait Resaurant2[N1<:Nationality,N2<:Nationality] extends Restaurant { def m1(implicit man: reflect.Manifest[N1]) = man def m2(implicit man: reflect.Manifest[N2]) = man def feed(customer:Nationality) = { if (m1.erasure == customer.getClass) "somedish" else "sorry" if (m2.erasure == customer.getClass) "anotherdish" else "sorry" } } val restaurants = List(new Restaurant1[Chinese], new Restaurant2[Chinese,Japanese]) val customer = new Nationality[Japanese] println(restaurants.map(r => r.feed(customer))) I could accomplish this by asking my library users to set an instance variable in the trait, but I'm designing a DSL, and a very much want it to be succinct and pretty. I'd be very appreciative of any help or pointers. Best wishes, Andrew
|
|
|
Re: [scala] Constructor parameters for traitsI believe this does what you want:
% scala andrew Trying to feed a Japanese at a restaurant serving Chinese Trying to feed a Japanese at a restaurant serving Chinese, Japanese // begin code trait Nationality trait Italian extends Nationality { override def toString() = "Italian" } trait Chinese extends Nationality { override def toString() = "Chinese" } trait Japanese extends Nationality { override def toString() = "Japanese" } trait Korean extends Nationality { override def toString() = "Korean" } trait Restaurant { def feed(customer: Nationality): String def status(customer: String, dishes: String) = "Trying to feed a %s at a restaurant serving %s".format(customer, dishes) } class Restaurant1Class[N1 <: Nationality](implicit m1: reflect.Manifest[N1]) extends Restaurant { def feed(customer: Nationality) = { status(customer.toString, m1.toString) } } trait Restaurant1[N1 <: Nationality] extends Restaurant1Class[N1] class Restaurant2Class[N1 <: Nationality, N2 <: Nationality]( implicit m1: reflect.Manifest[N1], m2: reflect.Manifest[N2]) extends Restaurant { def feed(customer: Nationality) = { status(customer.toString, List(m1, m2).mkString(", ")) } } trait Restaurant2[N1 <: Nationality, N2 <: Nationality] extends Restaurant2Class[N1, N2] object andrew { def main(args: Array[String]): Unit = { val restaurants = List(new Restaurant1[Chinese] {}, new Restaurant2[Chinese, Japanese] {}) val customer = new Japanese {} restaurants map (_ feed customer) foreach println } } -- Paul Phillips | It's not enough to bash in heads - you've got to Everyman | bash in minds. Empiricist | -- Capt Hammer i'll ship a pulp |----------* http://www.improving.org/paulp/ *---------- |
|
|
Re: [scala] Constructor parameters for traitsBeing a sucker for questions about typing and implicits, here's my shot:
trait Nationality class Italian extends Nationality class Chinese extends Nationality class Japanese extends Nationality
class Korean extends Nationality trait Restaurant { def feed(customer:Nationality) : String } object Restaurant1 { def apply[N1<:Nationality](implicit man1: reflect.Manifest[N1]) = new Restaurant1[N1]{val m1 = man1}
} trait Restaurant1[N1<:Nationality] extends Restaurant { implicit val m1: reflect.Manifest[N1] def feed(customer:Nationality) = if (m1.erasure == customer.getClass) "dish" else "sorry"
} object Restaurant2 { def apply[N1<:Nationality,N2<:Nationality](implicit man1: reflect.Manifest[N1], man2: reflect.Manifest[N2]) = new Restaurant2[N1, N2]{val m1 = man1; val m2 = man2}
} trait Restaurant2[N1<:Nationality,N2<:Nationality] extends Restaurant { implicit val m1: reflect.Manifest[N1] implicit val m2: reflect.Manifest[N2] def feed(customer:Nationality) = if (m1.erasure == customer.getClass) "somedish" else if (m2.erasure == customer.getClass) "anotherdish" else "sorry"
} object Test extends Application { val restaurants = List(Restaurant1[Chinese], Restaurant2[Chinese,Japanese]) val customer = new Japanese println(restaurants.map(r => r.feed(customer)))
} BTW: I would model nationalities differently -- Japanese should be an object, not a trait On Mon, Aug 31, 2009 at 2:32 PM, Paul Phillips <paulp@...> wrote: I believe this does what you want: |
|
|
|
| Free embeddable forum powered by Nabble | Forum Help |