Scala 2.8 best practices about clone / copy constructor / factory / etc ?

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 ?

by Francois Armand-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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 ?

by Sébastien Bocq :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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


Re: Scala 2.8 best practices about clone / copy constructor / factory / etc ?

by Sébastien Bocq :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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



Re: Scala 2.8 best practices about clone / copy constructor / factory / etc ?

by Marcus Downing :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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?



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@gmail.com>

> 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@gmail.com>
>
> 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 ?

by David Hall-17 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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 ?

by Sébastien Bocq :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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@...>
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 ?

by Francois Armand-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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 ?

by Marcus Downing :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Francois-17 wrote:
So, for now, I'm really disappointed with named argument and cloning in
Scala.
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 ?

by Francois Armand-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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 ?

by Sébastien Bocq :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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@...>


Francois-17 wrote:
>
> So, for now, I'm really disappointed with named argument and cloning in
> Scala.
>

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?
--
View this message in context: http://old.nabble.com/Scala-2.8-best-practices-about-clone---copy-constructor---factory---etc---tp26023568p26198701.html
Sent from the Scala - User mailing list archive at Nabble.com.



Re: Scala 2.8 best practices about clone / copy constructor / factory / etc ?

by Marcus Downing :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Sébastien Bocq wrote:
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 {
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 ?

by Francois Armand-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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 ?

by Nils Kilden-Pedersen :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Thu, Nov 5, 2009 at 9:26 AM, Francois <fanf42@...> wrote:

So please, show me the pattern, I'm really just asking for that !


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 ?

by Dean Wampler-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

+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:
On Thu, Nov 5, 2009 at 9:26 AM, Francois <fanf42@...> wrote:

So please, show me the pattern, I'm really just asking for that !


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.



--
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 ?

by Sébastien Bocq :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

2009/11/5 Marcus Downing <marcus@...>

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.


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 ?

by Marcus Downing :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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.


Francois-17 wrote:
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 ?

by Sébastien Lorion-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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:

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.



Francois-17 wrote:
>
> 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
>
>

--
View this message in context: http://old.nabble.com/Scala-2.8-best-practices-about-clone---copy-constructor---factory---etc---tp26023568p26218569.html
Sent from the Scala - User mailing list archive at Nabble.com.



Re: Scala 2.8 best practices about clone / copy constructor / factory / etc ?

by Sébastien Bocq :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



2009/11/5 Marcus Downing <marcus@...>


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)
}

 
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?

by phkoester :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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?

by David Hall-17 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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 >