|
View:
New views
18 Messages
—
Rating Filter:
Alert me
|
| < Prev | 1 - 2 | Next > |
|
|
Re: Dependency injection in Scala?On 2/4/08, Jamie Webb <j@...> wrote:
> On 2008-02-03 20:45:54 Stepan Koltsov wrote: > > This does not work well. > > > > 1. If Sensor component is used in two different places (in Warmer and > > in Cooler), it will be instantiated twice. > > No, it won't. Read again. Actually it will without structural subtyping. === class Sensor { println("new Sensor") } abstract class Warmer { trait Env { val sensor: Sensor } protected val env: Env } abstract class Cooler { trait Env { val sensor: Sensor } protected val env: Env } object App { val theSensor = new Sensor val theWarmer = new Warmer { val env = new Config with Env } val theCooler = new Cooler { val env = new Config with Env } class Config { println("new Config") lazy val sensor = new Sensor lazy val warmer = theWarmer lazy val cooler = theCooler } object Config extends Config } println(App.Config.cooler) println(App.Config.warmer) println(App.Config.cooler.env.sensor) println(App.Config.warmer.env.sensor) println(App.Config.cooler.env.sensor) println(App.Config.warmer.env.sensor) === prints "new Sensor" three times. > > 2. Synax overhead: I have to declare each components two times: first > > before Config class, and second inside Config. > > Well, if you want to reduce the keystrokes further, here's the version > I mentioned using structural subtyping: > > class Warmer(env : { > val potSensor : SensorDevice > val heater : OnOffDevice > }) { > def trigger() { > if(env.potSensor.isCoffeePresent) env.heater.on() > else env.heater.off() > } > } > > object Config { > lazy val potSensor = new PotSensor > lazy val heater = new Heater > lazy val warmer = new Warmer(this) > } > > Quite pretty, really... This does not allow Warmer and Cooler to have "sensor" parameter that are set to different beans. S. |
|
|
Re: Dependency injection in Scala?On Mon, 2008-02-04 at 15:49 +0300, Stepan Koltsov wrote:
> Actually it will without structural subtyping. > > val theSensor = new Sensor > val theWarmer = new Warmer { val env = new Config with Env } > val theCooler = new Cooler { val env = new Config with Env } > > class Config { > println("new Config") > lazy val sensor = new Sensor > lazy val warmer = theWarmer > lazy val cooler = theCooler > } > > object Config extends Config Shouldn't it say "val env = Config with Env", not "val env = new Config with Env"? And why do you create "val theSensor = new Sensor" ? The Config is responsible for creating the sensor. So that accounts for one of the three, and the fact you create 2 Config class instances accounts for the other 2 sensors. Hope that clarifies this example :) Robin |
|
|
Re: Dependency injection in Scala?On 2/4/08, Robin Message <rhm31@...> wrote:
> On Mon, 2008-02-04 at 15:49 +0300, Stepan Koltsov wrote: > > Actually it will without structural subtyping. > > > > val theSensor = new Sensor > > val theWarmer = new Warmer { val env = new Config with Env } > > val theCooler = new Cooler { val env = new Config with Env } > > > > class Config { > > println("new Config") > > lazy val sensor = new Sensor > > lazy val warmer = theWarmer > > lazy val cooler = theCooler > > } > > > > object Config extends Config > > Shouldn't it say "val env = Config with Env", not "val env = new Config > with Env"? > > And why do you create "val theSensor = new Sensor" ? The Config is > responsible for creating the sensor. So that accounts for one of the > three, and the fact you create 2 Config class instances accounts for the > other 2 sensors. > > Hope that clarifies this example :) Could you please paste here complete compileable example? S. |
|
|
Re: Dependency injection in Scala?Scratch that, ignore me.
In future, I promise to test if my answers actually even compile. Robin |
|
|
Re: Dependency injection in Scala?On 2008-02-04 15:49:55 Stepan Koltsov wrote:
> object App { > val theSensor = new Sensor > val theWarmer = new Warmer { val env = new Config with Env } > val theCooler = new Cooler { val env = new Config with Env } > > class Config { > println("new Config") > lazy val sensor = new Sensor Why have you changed this line? Change it back to 'theSensor' and your problem goes away. > > class Warmer(env : { > > val potSensor : SensorDevice > > val heater : OnOffDevice > > }) { > > def trigger() { > > if(env.potSensor.isCoffeePresent) env.heater.on() > > else env.heater.off() > > } > > } > > > > object Config { > > lazy val potSensor = new PotSensor > > lazy val heater = new Heater > > lazy val warmer = new Warmer(this) > > } > > > > Quite pretty, really... > > This does not allow Warmer and Cooler to have "sensor" parameter that > are set to different beans. It does, but it means forgoing autowiring for that particular bean. This would be fixed if Scala supported the often-requested 'export' statement. Of course the first version I posted doesn't have this problem. /J |
|
|
Re: Dependency injection in Scala?Why using subtyping or nested trait, a simple and classical constructor dependency injection is enough:
class Sensor { println("new Sensor") } class Warmer(val sensor: Sensor) { // do something } class Cooler(val sensor: Sensor) { // do something } object Test extends Application { class Config { println("new Config") lazy val sensor = new Sensor lazy val warmer = new Warmer(sensor) lazy val cooler = new Cooler(sensor) } object Config extends Config println(Config.cooler) println(Config.warmer) println(Config.cooler.sensor) println(Config.warmer.sensor) } /davidB Stepan Koltsov wrote: > On 2/4/08, Jamie Webb <j@...> wrote: >> On 2008-02-03 20:45:54 Stepan Koltsov wrote: >>> This does not work well. >>> >>> 1. If Sensor component is used in two different places (in Warmer and >>> in Cooler), it will be instantiated twice. >> No, it won't. Read again. > > Actually it will without structural subtyping. > > === > class Sensor { > println("new Sensor") > } > > abstract class Warmer { > trait Env { > val sensor: Sensor > } > > protected val env: Env > } > > abstract class Cooler { > trait Env { > val sensor: Sensor > } > > protected val env: Env > } > > object App { > val theSensor = new Sensor > val theWarmer = new Warmer { val env = new Config with Env } > val theCooler = new Cooler { val env = new Config with Env } > > class Config { > println("new Config") > lazy val sensor = new Sensor > lazy val warmer = theWarmer > lazy val cooler = theCooler > } > > object Config extends Config > } > > println(App.Config.cooler) > println(App.Config.warmer) > println(App.Config.cooler.env.sensor) > println(App.Config.warmer.env.sensor) > println(App.Config.cooler.env.sensor) > println(App.Config.warmer.env.sensor) > > === > > prints "new Sensor" three times. > >>> 2. Synax overhead: I have to declare each components two times: first >>> before Config class, and second inside Config. >> Well, if you want to reduce the keystrokes further, here's the version >> I mentioned using structural subtyping: >> >> class Warmer(env : { >> val potSensor : SensorDevice >> val heater : OnOffDevice >> }) { >> def trigger() { >> if(env.potSensor.isCoffeePresent) env.heater.on() >> else env.heater.off() >> } >> } >> >> object Config { >> lazy val potSensor = new PotSensor >> lazy val heater = new Heater >> lazy val warmer = new Warmer(this) >> } >> >> Quite pretty, really... > > This does not allow Warmer and Cooler to have "sensor" parameter that > are set to different beans. > > S. |
|
|
Re: Dependency injection in Scala?On 2008-02-04 14:23:44 David Bernard wrote:
> Why using subtyping or nested trait, a simple and classical > constructor dependency injection is enough: > > class Sensor { > println("new Sensor") > } > > class Warmer(val sensor: Sensor) { > // do something > } > > class Cooler(val sensor: Sensor) { > // do something > } > > object Test extends Application { > class Config { > println("new Config") > lazy val sensor = new Sensor > lazy val warmer = new Warmer(sensor) > lazy val cooler = new Cooler(sensor) > } > > object Config extends Config > > println(Config.cooler) > println(Config.warmer) > println(Config.cooler.sensor) > println(Config.warmer.sensor) > } The trouble with this approach is that there's no autowiring; you have to manually list all the dependencies of every object, which gets quite tedious. Incidentally, your example above will not work with cyclic dependencies; you would need to make the constructor parameters call-by-name. /J |
|
|
Re: Dependency injection in Scala?On 2/4/08, Jamie Webb <j@...> wrote:
> On 2008-02-04 15:49:55 Stepan Koltsov wrote: > > object App { > > val theSensor = new Sensor > > val theWarmer = new Warmer { val env = new Config with Env } > > val theCooler = new Cooler { val env = new Config with Env } > > > > class Config { > > println("new Config") > > lazy val sensor = new Sensor > > Why have you changed this line? Change it back to 'theSensor' and your > problem goes away. Oops. Sorry. S. |
|
|
Re: Dependency injection in Scala?Hi guys.
Thanks for a great discussion. I was wondering if there is a reason why nobody has mentioned using implicits. E.g. what is wrong with the following code (using Jamie's example)? Thanks, Jonas. trait OnOffDevice { def on() : Unit def off() : Unit } trait SensorDevice { def isCoffeePresent : Boolean } class Heater extends OnOffDevice { def on() = println("heater on") def off() = println("heater off") } class PotSensor extends SensorDevice { def isCoffeePresent = true } class Warmer(implicit val sensor: SensorDevice, implicit val onOff: OnOffDevice) { def trigger() { if (sensor.isCoffeePresent) onOff.on() else onOff.off() } } object Services { implicit val potSensor = new PotSensor implicit val heater = new Heater } object Client extends Application { import Services._ val warmer = new Warmer warmer.trigger } On 04/02/2008, Stepan Koltsov <stepan.koltsov@...> wrote: > On 2/4/08, Jamie Webb <j@...> wrote: > > On 2008-02-04 15:49:55 Stepan Koltsov wrote: > > > object App { > > > val theSensor = new Sensor > > > val theWarmer = new Warmer { val env = new Config with Env } > > > val theCooler = new Cooler { val env = new Config with Env } > > > > > > class Config { > > > println("new Config") > > > lazy val sensor = new Sensor > > > > Why have you changed this line? Change it back to 'theSensor' and your > > problem goes away. > > Oops. Sorry. > > S. > -- Jonas Bonér http://jonasboner.com |
|
|
Re: Dependency injection in Scala?On 2/4/08, Jonas Bonér <lists@...> wrote:
I was wondering if there is a reason why nobody has mentioned using implicits. Good point! Yet another example where Scala natively provides a compelling alternative to Java dependency injection frameworks. alex |
|
|
Re: Dependency injection in Scala?That looks like an interesting approach to autowiring. I haven't yet
seen implicit used on constructor arguments (or whatever they are called). The examples in ScalaByExample show implicit parameters on method arguments and objects... Are there more example available somewhere? Jörn On Feb 4, 2008 6:39 PM, Jonas Bonér <lists@...> wrote: > Hi guys. > > Thanks for a great discussion. > > I was wondering if there is a reason why nobody has mentioned using implicits. > E.g. what is wrong with the following code (using Jamie's example)? > > Thanks, Jonas. > > trait OnOffDevice { > def on() : Unit > def off() : Unit > } > > trait SensorDevice { > def isCoffeePresent : Boolean > } > > class Heater extends OnOffDevice { > def on() = println("heater on") > def off() = println("heater off") > } > > class PotSensor extends SensorDevice { > def isCoffeePresent = true > } > > class Warmer(implicit val sensor: SensorDevice, implicit val onOff: > OnOffDevice) { > def trigger() { > if (sensor.isCoffeePresent) onOff.on() > else onOff.off() > } > } > > object Services { > implicit val potSensor = new PotSensor > implicit val heater = new Heater > } > > object Client extends Application { > import Services._ > > val warmer = new Warmer > warmer.trigger > } > > > On 04/02/2008, Stepan Koltsov <stepan.koltsov@...> wrote: > > > On 2/4/08, Jamie Webb <j@...> wrote: > > > On 2008-02-04 15:49:55 Stepan Koltsov wrote: > > > > object App { > > > > val theSensor = new Sensor > > > > val theWarmer = new Warmer { val env = new Config with Env } > > > > val theCooler = new Cooler { val env = new Config with Env } > > > > > > > > class Config { > > > > println("new Config") > > > > lazy val sensor = new Sensor > > > > > > Why have you changed this line? Change it back to 'theSensor' and your > > > problem goes away. > > > > Oops. Sorry. > > > > S. > > > > > -- > Jonas Bonér > > http://jonasboner.com > |
|
|
Re: Dependency injection in Scala?On 04/02/2008, Jörn Zaefferer <joern.zaefferer@...> wrote:
> That looks like an interesting approach to autowiring. I haven't yet > seen implicit used on constructor arguments (or whatever they are > called). The examples in ScalaByExample show implicit parameters on > method arguments and objects... Are there more example available > somewhere? I haven't seen any. Just made it up. That's why I wanted to ask the experts if I had missed something or if it actually could work generically as simple as it is. > > Jörn > > On Feb 4, 2008 6:39 PM, Jonas Bonér <lists@...> wrote: > > Hi guys. > > > > Thanks for a great discussion. > > > > I was wondering if there is a reason why nobody has mentioned using implicits. > > E.g. what is wrong with the following code (using Jamie's example)? > > > > Thanks, Jonas. > > > > trait OnOffDevice { > > def on() : Unit > > def off() : Unit > > } > > > > trait SensorDevice { > > def isCoffeePresent : Boolean > > } > > > > class Heater extends OnOffDevice { > > def on() = println("heater on") > > def off() = println("heater off") > > } > > > > class PotSensor extends SensorDevice { > > def isCoffeePresent = true > > } > > > > class Warmer(implicit val sensor: SensorDevice, implicit val onOff: > > OnOffDevice) { > > def trigger() { > > if (sensor.isCoffeePresent) onOff.on() > > else onOff.off() > > } > > } > > > > object Services { > > implicit val potSensor = new PotSensor > > implicit val heater = new Heater > > } > > > > object Client extends Application { > > import Services._ > > > > val warmer = new Warmer > > warmer.trigger > > } > > > > > > On 04/02/2008, Stepan Koltsov <stepan.koltsov@...> wrote: > > > > > On 2/4/08, Jamie Webb <j@...> wrote: > > > > On 2008-02-04 15:49:55 Stepan Koltsov wrote: > > > > > object App { > > > > > val theSensor = new Sensor > > > > > val theWarmer = new Warmer { val env = new Config with Env } > > > > > val theCooler = new Cooler { val env = new Config with Env } > > > > > > > > > > class Config { > > > > > println("new Config") > > > > > lazy val sensor = new Sensor > > > > > > > > Why have you changed this line? Change it back to 'theSensor' and your > > > > problem goes away. > > > > > > Oops. Sorry. > > > > > > S. > > > > > > > > > -- > > Jonas Bonér > > > > http://jonasboner.com40 > > > -- Jonas Bonér http://jonasboner.com |
|
|
Re: Dependency injection in Scala?On Feb 4, 2008 2:07 PM, Jonas Bonér <lists@...> wrote:
> On 04/02/2008, Jörn Zaefferer <joern.zaefferer@...> wrote: > > That looks like an interesting approach to autowiring. I haven't yet > > seen implicit used on constructor arguments (or whatever they are > > called). The examples in ScalaByExample show implicit parameters on > > method arguments and objects... Are there more example available > > somewhere? > > I haven't seen any. Just made it up. That's why I wanted to ask the > experts if I had missed something or if it actually could work > generically as simple as it is. Should do. There are a few issues with the type inferencer and similar which make it slightly annoying to use, and it's still relatively verbose, but it should work. And with call by name parameters you can probably even make it support circular dependencies. (I've looked into doing this before but never really tried it out in practice) |
|
|
Re: Dependency injection in Scala?Debasish's latest post in his blog is about scala and DI
http://debasishg.blogspot.com/2008/02/scala-to-di-or-not-to-di.html His conclusion favors the use of a DI framework in spite of scala's niceties. I'm not sure to follow all the reasons but you guys probably will :) |
|
|
Re: Dependency injection in Scala?On 04 Feb 2008, at 18:39, Jonas Bonér wrote: > I was wondering if there is a reason why nobody has mentioned using > implicits. Glad you asked :-) Buried in a seemingly unrelated thread, I said: http://article.gmane.org/gmane.comp.lang.scala.user/2546 adriaan |
|
|
Re: Dependency injection in Scala?Hi Adriaan,
would you mind repeating your post here? It seems like the example you posted is incomplete and the attachment gone. So far implicits seem to be the language constuct that get "native" DI in scala closest to autowiring in Spring, which I'm using a lot. More details or examples are much appreciated. Jörn On Feb 5, 2008 11:15 AM, Adriaan Moors <adriaan.moors@...> wrote: > > On 04 Feb 2008, at 18:39, Jonas Bonér wrote: > > I was wondering if there is a reason why nobody has mentioned using > > implicits. > Glad you asked :-) > Buried in a seemingly unrelated thread, I said: http://article.gmane.org/gmane.comp.lang.scala.user/2546 > > adriaan |
|
|
Re: Dependency injection in Scala?Hi Jörn,
I've attached the full example. The basic idea is to use implicits, so that we can have a type drive the selection of a value. (Which amounts to ad-hoc polymorphism, akin to Java's static overloading.) More concretely, you could never implement the following class, as there's no way of making a T without knowing what it is. trait Factory[+T] { def make: T } Abstracting over a type means that you should not care what that type is. (Technically, erasure keeps you from doing this. In a language with run-time types, you could use reflection.) However, if we throw implicits into the mix: def makeDatabase(implicit factory: Factory[Database]): Database = factory.make We can call makeDatabase whenever an implicit value of type Factory[Database] is in scope. Thus, by specifying a *type* (Database), the compiler finds a *value* for us to do the heavy lifting. Of course you can make makeDatabase more abstract, as shown in the attached example. hth adriaan On 05 Feb 2008, at 14:36, Jörn Zaefferer wrote: > Hi Adriaan, > > would you mind repeating your post here? It seems like the example you > posted is incomplete and the attachment gone. > > So far implicits seem to be the language constuct that get "native" DI > in scala closest to autowiring in Spring, which I'm using a lot. > > More details or examples are much appreciated. > > Jörn > > On Feb 5, 2008 11:15 AM, Adriaan Moors > <adriaan.moors@...> wrote: >> >> On 04 Feb 2008, at 18:39, Jonas Bonér wrote: >>> I was wondering if there is a reason why nobody has mentioned using >>> implicits. >> Glad you asked :-) >> Buried in a seemingly unrelated thread, I said: http://article.gmane.org/gmane.comp.lang.scala.user/2546 >> >> adriaan > |
|
|
Re: Dependency injection in Scala?In the context of this discussion, it might be interesting to see what
the Groovy people are doing, with something called the Groovy Spring Bean builder http://grails.codehaus.org/Spring+Bean+Builder It seems like something DSL-oriented is a nice approach in this case. Patrick |
| < Prev | 1 - 2 | Next > |
| Free embeddable forum powered by Nabble | Forum Help |