|
View:
New views
20 Messages
—
Rating Filter:
Alert me
|
| < Prev | 1 - 2 - 3 | Next > |
|
|
Scala 2.8 best practices about clone / copy constructor / factory / etc ?Hello,
I'm in the process of building a my domain model and I'm wondering what are the Scala best practices regarding the cloning subject for inheritance hierarchy. A typical example of hierarchy could be: ========================== class Person(val name : String) { var address : Adress } class Child(val father : Person, val mother : Person) { val brothers = Buffer[Person]() } trait HasPassword { var pwd : String } class User(val login : String) extends User with HasPassword { ... } ========================== It is of course just an example of the different use cases that I encountered, and maybe there are a lots of other than just class and/or trait with val and/or vars and/or (im)mutable collections. So, what are the best practices to minimize code duplication and be able to make deep copies of objects ? Case with only vals (immutable state in general) are rather simple, but there are all the others... I saw somewhere that 2.8 named/defaults arguments may bring some great enhancement in this area, but I can't find any resources about that anymore. Thanks in advance for all the good advice you scalazies will give ! -- Francois Armand |
|
|
Re: Scala 2.8 best practices about clone / copy constructor / factory / etc ?Hi,
I'm struggling with this too. Is there any cloning support in 2.8 like found in some prototype-based languages? Maybe 'clone' could be a keyword used like this: trait Person { val name:String val other = "XXX" } trait Question { val q:String } val fanf = new Person with Question {val name="fanf"; val q="What about clone?"} val seb = clone fanf {val name="seb"} Any suggestion? Thanks, Sebastien 2009/10/23 Francois <fanf42@...> Hello, |
|
|
Re: Scala 2.8 best practices about clone / copy constructor / factory / etc ?Or maybe better, no new keyword as it would cause many issues.
val seb = new fanf {val name="seb"} 2009/10/31 Sébastien Bocq <sebastien.bocq@...> Hi, |
|
|
Re: Scala 2.8 best practices about clone / copy constructor / factory / etc ?I seem to remember hearing that 2.8 will use named and default arguments to automatically generate copy methods for case classes, as described here: http://www.scala-lang.org/node/2075
val seb = fanf.copy(name="seb") You could achieve the same result yourself for non-case classes: def copy (name = this.name, other = this.other) = new Person(name, other) I'm not using the 2.8 nightlies myself, so does somebody who is want to confirm this?
|
|
|
Re: Scala 2.8 best practices about clone / copy constructor / factory / etc ?On Sat, Oct 31, 2009 at 3:39 PM, Marcus Downing <marcus@...> wrote:
> > I seem to remember hearing that 2.8 will use named and default arguments to > automatically generate copy methods for case classes, as described here: > http://www.scala-lang.org/node/2075 > > val seb = fanf.copy(name="seb") > > You could achieve the same result yourself for non-case classes: > > def copy (name = this.name, other = this.other) = new Person(name, other) > > I'm not using the 2.8 nightlies myself, so does somebody who is want to > confirm this? I use this, and it makes me happy. -- David > > > > > Sébastien Bocq wrote: >> >> Or maybe better, no new keyword as it would cause many issues. >> >> val seb = new fanf {val name="seb"} >> >> 2009/10/31 Sébastien Bocq <sebastien.bocq@...> >> >>> Hi, >>> >>> I'm struggling with this too. Is there any cloning support in 2.8 like >>> found in some prototype-based languages? >>> >>> Maybe 'clone' could be a keyword used like this: >>> >>> trait Person { >>> val name:String >>> val other = "XXX" >>> } >>> >>> trait Question { >>> val q:String >>> } >>> >>> val fanf = new Person with Question {val name="fanf"; val q="What about >>> clone?"} >>> >>> val seb = clone fanf {val name="seb"} >>> >>> Any suggestion? >>> >>> Thanks, >>> Sebastien >>> >>> 2009/10/23 Francois <fanf42@...> >>> >>> Hello, >>>> >>>> I'm in the process of building a my domain model and I'm wondering what >>>> are the Scala best practices regarding the cloning subject for >>>> inheritance >>>> hierarchy. >>>> >>>> A typical example of hierarchy could be: >>>> >>>> ========================== >>>> class Person(val name : String) { >>>> var address : Adress >>>> } >>>> >>>> class Child(val father : Person, val mother : Person) { >>>> val brothers = Buffer[Person]() >>>> } >>>> >>>> trait HasPassword { >>>> var pwd : String >>>> } >>>> >>>> class User(val login : String) extends User with HasPassword { >>>> ... >>>> } >>>> ========================== >>>> >>>> It is of course just an example of the different use cases that I >>>> encountered, and maybe there are a lots of other than just class and/or >>>> trait with val and/or vars and/or (im)mutable collections. >>>> >>>> So, what are the best practices to minimize code duplication and be able >>>> to make deep copies of objects ? >>>> >>>> Case with only vals (immutable state in general) are rather simple, but >>>> there are all the others... >>>> >>>> I saw somewhere that 2.8 named/defaults arguments may bring some great >>>> enhancement in this area, but I can't find any resources about that >>>> anymore. >>>> >>>> >>>> Thanks in advance for all the good advice you scalazies will give ! >>>> >>>> -- >>>> Francois Armand >>>> >>> >>> >> >> > > -- > View this message in context: http://old.nabble.com/Scala-2.8-best-practices-about-clone---copy-constructor---factory---etc---tp26023568p26146603.html > Sent from the Scala - User mailing list archive at Nabble.com. > > |
|
|
Re: Scala 2.8 best practices about clone / copy constructor / factory / etc ?Thanks for the suggestion but unfortunately this pattern doesn't scale with mixin composition. For example if X is a trait, you can't do "new A with X" and inherit automatically the copy behavior of X. Take for example the trait Person I made earlier, you can't implement copy there.
My question is how to use mixins and code the immutable way in a scalable manner? 2009/10/31 David Hall <dlwh@...>
|
|
|
Re: Scala 2.8 best practices about clone / copy constructor / factory / etc ?Sébastien Bocq a écrit :
> Or maybe better, no new keyword as it would cause many issues. > > val seb = new fanf {val name="seb"} Well, for now, the best I came with is what I posted here: http://fanf42.blogspot.com/2009/10/clone-objects-with-arguments-override.html It allows to make clone like that : val fanf = new Person("fanf", "What's your name ?") { var age = 28 } val fanf2 = fanf.copy val foo = fanf.copyWith(name = "foo", age = "42") But it leads to awful amount of code duplication in class hierrachy because each daughter class has to declare it's own "copyWith" method with all its ancestor named argument. And that means that if an ancestor parameter is modified (added/suppressed or even just name changed), we have to replicate the change in ALL the hierarchy. So, for now, I'm really disappointed with named argument and cloning in Scala. -- Francois Armand http://fanf42.blogspot.com |
|
|
Re: Scala 2.8 best practices about clone / copy constructor / factory / etc ?It does exactly the right thing for case classes, automatically generates a copy() method. It's only normal classes that it doesn't do it for, and it's assumed that the values of a non-case class might be sufficiently complicated that a straightforward copy is inaccurate. For example, what happens if you attempt to copy() a JDBC Connection? Or a File? |
|
|
Re: Scala 2.8 best practices about clone / copy constructor / factory / etc ?On 04/11/2009 16:45, Marcus Downing wrote:
> It does exactly the right thing for case classes, automatically generates a > copy() method. It's only normal classes that it doesn't do it for, and it's > assumed that the values of a non-case class might be sufficiently > complicated that a straightforward copy is inaccurate. > > For example, what happens if you attempt to copy() a JDBC Connection? Or a > File? I didn't mean that Scala should auto-generate clone or copy methods, I meant that Named arguments seemed to be a fabulous tool to build really powerful and flexible copy method in Scala, but that my experiment so for is quite disapointing, especially when class hierarchies and/or vars are involved, with a lot of tedious code to write and almost copy/paste in each level of the hierarchy. Of course, there is no magic, and the semantic of a copy method should be let to the user - safe in non ambiguous cases like for immutable case classes with no parents defining a copy method. For now, I will stay with what I have, but I will have to spend some strict tests process on that methods to check them along their life... -- Francois Armand http://fanf42.blogspot.com |
|
|
Re: Scala 2.8 best practices about clone / copy constructor / factory / etc ?I played a bit with those concepts and came up with the contrived example below. Although it is probably better this way, `copy` in case classes doesn't perform a real copy of the object, not even a shallow copy.
scala> trait File { | val filename:String | var fd:Int = _ | def open() {fd = filename.hashCode} | def write(s:String) = println("Writing " + s + " to " | } defined trait File scala> case class Person(name:String) extends File { | val filename = "/home/"+name+"/config.json" | } defined class Person scala> val seb = Person("seb") seb: Person = Person(seb) scala> seb.open scala> seb.write("Hello") Writing Hello to -1245076908 scala> val fanf = seb.copy(name = "fanf") fanf: Person = Person(fanf) scala> fanf.write("Hello") Writing Hello to 0 scala> fanf.filename res8: java.lang.String = /home/fanf/config.json Although it would yield a similar objects, I can't mixin behaviors dynamically into case classes: scala> case class Person(name:String) defined class Person scala> val seb = Person(name:String) with File { <console>:1: error: ';' expected but 'with' found. val seb = Person(name:String) with File { In my opinion, as long as this is not possible to copy easily other objects than those obtained from case classes, Scala will impose limitations that make immutability unpractical at a large scale. It is probably not for tomorrow but it would be nice if Scala could fuse OO, FP and prototype-based paradigms in a safe manner! Thanks for the feedback, Sebastien 2009/11/4 Marcus Downing <marcus@...>
|
|
|
Re: Scala 2.8 best practices about clone / copy constructor / factory / etc ?That's because Person(name) isn't a constructor, it's a method of the Person companion object. If you use the constructor then it works just fine: scala> val seb = new Person(name) with File <beginner> To explain the difference (if this is below your level I apologise), when you write a case class the compiler automatically generates a companion object with an apply() method that can be used in place of a constructor (and a matching unapply method for pattern matching). So writing this: case class Person (name: String) Is like writing this: class Person (name: String) { // a whole bunch of other auto-generated stuff } object Person { def apply(name: String) = new Person(name) } And then writing Person(name) is a shortcut for Person.apply(name) </beginner> I don't understand what it is you don't like about the named and default arguments. They provide a neat pattern for writing copy methods (far neater and safer than the pattern you came up with on your blog). The copy method is automatically created for case classes, but not for ordinary classes. This is entirely in keeping with the rest of the language: a case class is an immutable data type where you can trust that the compiler knows best, an non-case class is one where you define the behaviour for yourself. |
|
|
Re: Scala 2.8 best practices about clone / copy constructor / factory / etc ?On 05/11/2009 14:05, Marcus Downing wrote:
> I don't understand what it is you don't like about the named and default > arguments. They provide a neat pattern for writing copy methods (far neater > and safer than the pattern you came up with on your blog). OK, so it's the neat pattern that I'm missing and looking for. And I'm pretty sure I used named/default arguments on my blog. So, my requirements are: - I have classes with vals and vars - these classes are organized in hierarchies and aspects (I have both traits and classes hierarchies) That means that I'm out of the "case class" really specific case that is the simple one that works well. Given only that, I want to find a pattern to let developers implement deep copies of instances writting the less code (and so, using again the most code from parents/traits/factories/whatever), and where I have the possibility to modify some values of the copy on the fly, based on the properties names (so clearly here, default and named arguments are involved). Ah, of course, I do want to have a returned copy of the same type as the copied object. Traits included. So please, show me the pattern, I'm really just asking for that ! Some hints about what I had to deal with: - vars and constructors don't go well together with inheritance ; - if traits are involved, you will need some kind of "only copy the property I own but deals correctly with input/output type of the clone" - covariance and inheritance is funny to deal with - named arguments and inheritance is funny, too. Well, if you like to copy/paste lists of arguments. -- Francois Armand |
|
|
Re: Scala 2.8 best practices about clone / copy constructor / factory / etc ?On Thu, Nov 5, 2009 at 9:26 AM, Francois <fanf42@...> wrote:
There's not really a good generic way to deal with what you want. Much like equality, cloning, and particularly deep cloning, are context specific. I've tried this before through reflection and it's not pretty. |
|
|
Re: Scala 2.8 best practices about clone / copy constructor / factory / etc ?+1. I also can't remember the last time I really needed a deep clone of an object graph. It has performance issues, in addition to the issues already discussed. Unless my memory fails me, I've always found an alternative design.
My view is that the best, general model is a persistent data structure, like the Bagwell persistent collections used in Clojure for STM and "coming soon to a Scala near you". It safely handles copy-on-write behavior, leaving other clients of the original data structure unaffected. Are there any scenarios where copy-on-write behavior won't work and deep cloning is essential?
dean
On Thu, Nov 5, 2009 at 11:13 AM, Nils Kilden-Pedersen <nilskp@...> wrote:
-- Dean Wampler coauthor of "Programming Scala" (O'Reilly) - http://programmingscala.com twitter: @deanwampler, @chicagoscala Chicago-Area Scala Enthusiasts (CASE): - http://groups.google.com/group/chicagoscala - http://www.meetup.com/chicagoscala/ (Meetings) http://www.linkedin.com/in/deanwampler http://www.polyglotprogramming.com http://aquarium.rubyforge.org http://www.contract4j.org |
|
|
Re: Scala 2.8 best practices about clone / copy constructor / factory / etc ?2009/11/5 Marcus Downing <marcus@...>
Personally I really like them, it is just that I miss this feature beyond case classes where I know it is also safe to copy the object. If Person is a regular class I can't use the neat copy method anymore but I can mixin traits dynamically. If Person is a case class, I can copy it for free but I can't mixin traits dynamically anymore. That was the idea behind the example. I understand the challenge and I'm wondering if there would be a way to unify these approaches in the future. |
|
|
Re: Scala 2.8 best practices about clone / copy constructor / factory / etc ?Deep copying is counter to the functional spirit of immutable objects and case classes that Scala espouses, so you'll have to write it yourself. However, the same pattern can still be used, with just one adaptation: you need to call the corresponding method of each of your variables:
class Foo (name: String) { def deepCopy(name = name) = new Foo(name) } class Bar (var foo: Foo) { def deepCopy(foo = foo.deepCopy) = new Bar(foo) } Strings don't need deep copying so Foo.deepCopy just needs to refer to its parameter. Foos apparently do need deep copying, so Bar.deepCopy calls foo.deepCopy as its parameter - unless the foo parameter is specified when the method is called. You may need to do some functional gymnastics to make sure it doesn't call foo.deepCopy unnecessarily. To apply this to a hierarchy of concrete classes, you will of course have to put a version of the deepCopy method into all of the classes, including children. Returning the correct type from objects to which you've applied a trait above that of the class itself is trickier. My first impulse is to tell you not to do it, but I have to assume you have your reasons. Unless somebody can come up with a better way, you're probably going to have to use good old Java reflection for that bit - however, you can wrap that bit of ugliness up in a trait: trait DeepCopyable { def internalDeepCopy(args: _*) = { // ugly reflection to create a new instance of val thisClass = classOf[this] thisClass.newInstance(args) } } Which would then be applied like this: class Bar (var foo: Foo) { def deepCopy(foo = foo.deepCopy) = internalDeepCopy(foo) } Yes, using reflection will be slower than an ordinary constructor. That's the price for deliberately walking off the nice clean fuctional path that Scala has laid out for you, onto the muddy grass of imperativeness. **** Note that none of the above is actually tested, I'm just braindumping.
|
|
|
Re: Scala 2.8 best practices about clone / copy constructor / factory / etc ?How serialization would fare as a way to do deep cloning with Scala ? Can't imagine having to do that manually or even worse via reflection ...
Sébastien On Thu, Nov 5, 2009 at 14:20, Marcus Downing <marcus@...> wrote:
|
|
|
Re: Scala 2.8 best practices about clone / copy constructor / factory / etc ?2009/11/5 Marcus Downing <marcus@...>
Suppose I just use immutable classes and traits, no vars, in most parts of my code. How would I implement a ShallowCopyable trait myself? I can't. |
|
|
Lazy Vals Thread-Safe?Dear list,
short question in the hope of a short answer: Are lazy vals in Scala implemented in a thread-safe fashion? ---Ph. |
|
|
Re: Lazy Vals Thread-Safe?yes. it uses double checked locking.
-- David On Fri, Nov 6, 2009 at 12:25 AM, Philip Köster <philip.koester@...> wrote: > Dear list, > > short question in the hope of a short answer: Are lazy vals in Scala > implemented in a thread-safe fashion? > > ---Ph. > |
| < Prev | 1 - 2 - 3 | Next > |
| Free embeddable forum powered by Nabble | Forum Help |