This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Abstracting on copy() method

5 replies
boisvert
Joined: 2009-11-11,
User offline. Last seen 38 weeks 5 days ago.
It is possible to abstract on the copy() method of case classes?

Here's roughtly what I'd like to do,

case class Foo(...)
case class Bar(...)

// I'm pretending there's something like the Copyable trait
def process(p: Product with Copyable) = {
  ...
  val copy = p.copy()
  ...
}

process(Foo(...))
process(Bar(...))

Mainly interested in a good answer for Scala 2.8.  My current alternative is the standard Java clone() method.  For performance reasons, I'm not so interested in the structural typing approach.

alex
Jason Zaugg
Joined: 2009-05-18,
User offline. Last seen 38 weeks 5 days ago.
Re: Abstracting on copy() method

Structural typing performance should be better in Scala 2.8. But it
wouldn't help in this case, as it doesn't allow you to omit parameters
and use the defaults.

Here's how it works with a regular, no-args method:

scala> class C { def copy() = 0}
defined class C

scala> val c = new C
c: C = C@85097d

scala> (c: { def copy(): Int }).copy
res8: Int = 0

And how it fails with named parameters:

scala> class C { def copy(a: Int = 0) = 0}
defined class C

scala> val c = new C
c: C = C@154024

scala> (c: { def copy(): Int }).copy
:7: error: type mismatch;
found : c.type (with underlying type C)
required: AnyRef{def copy(): Int}
(c: { def copy(): Int }).copy
^
Of course, you could try to be devious and use structural typing to
call the no args copy method, but you get a compiler crash. I'll
report a ticket for this crash if I can't find it already reported.

scala> c.getClass.getDeclaredMethods
res12: Array[java.lang.reflect.Method] = Array(public int
C.copy$default$1(), public int C.copy(int))

scala>(c: { def copy$default$1(): Int }).copy
Exception in thread "main" java.lang.AssertionError: assertion failed:
copy$default$1 at
scala.tools.nsc.symtab.Symbols$Symbol.info(Symbols.scala:747)

You would really need the compiler to synthesize a copyDefault method,
as per your suggestion of the Copyable trait.

-jason

On Wed, Mar 10, 2010 at 3:37 PM, Alex Boisvert wrote:
> It is possible to abstract on the copy() method of case classes?
>
> Here's roughtly what I'd like to do,
>
> case class Foo(...)
> case class Bar(...)
>
> // I'm pretending there's something like the Copyable trait
> def process(p: Product with Copyable) = {
>   ...
>   val copy = p.copy()
>   ...
> }
>
> process(Foo(...))
> process(Bar(...))
>
> Mainly interested in a good answer for Scala 2.8.  My current alternative is
> the standard Java clone() method.  For performance reasons, I'm not so
> interested in the structural typing approach.
>
> alex
>

dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: Abstracting on copy() method
Copy is really intended to create new instances of immutable objects with something changed. Clone is intended ot create identical instances of mutable objects. Given the almost complementary nature of each, why would you want a copy that works like a clone?

On Wed, Mar 10, 2010 at 11:37 AM, Alex Boisvert <alex [dot] boisvert [at] gmail [dot] com> wrote:
It is possible to abstract on the copy() method of case classes?

Here's roughtly what I'd like to do,

case class Foo(...)
case class Bar(...)

// I'm pretending there's something like the Copyable trait
def process(p: Product with Copyable) = {
  ...
  val copy = p.copy()
  ...
}

process(Foo(...))
process(Bar(...))

Mainly interested in a good answer for Scala 2.8.  My current alternative is the standard Java clone() method.  For performance reasons, I'm not so interested in the structural typing approach.

alex



--
Daniel C. Sobral

I travel to the future all the time.
boisvert
Joined: 2009-11-11,
User offline. Last seen 38 weeks 5 days ago.
Re: Abstracting on copy() method
On Wed, Mar 10, 2010 at 9:14 AM, Daniel Sobral <dcsobral [at] gmail [dot] com> wrote:
Copy is really intended to create new instances of immutable objects with something changed. Clone is intended ot create identical instances of mutable objects. Given the almost complementary nature of each, why would you want a copy that works like a clone?

Well, I thought about copy() because it's there and it's public.   (Reminder:  AnyRef.clone() is protected by default)

If case classes implemented Clonable and provided a public clone() method I would be a happy camper.  Any chance of this happening?

alex

dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: Abstracting on copy() method
Case classes don't _need_ a clone method in their normal usage. So, if you need clone, then you are likely doing something that's unusual and, therefore, difficult to write a clone for in an automated fashion. In fact, technically impossible, given the unknowns.

On Wed, Mar 10, 2010 at 2:54 PM, Alex Boisvert <alex [dot] boisvert [at] gmail [dot] com> wrote:
On Wed, Mar 10, 2010 at 9:14 AM, Daniel Sobral <dcsobral [at] gmail [dot] com> wrote:
Copy is really intended to create new instances of immutable objects with something changed. Clone is intended ot create identical instances of mutable objects. Given the almost complementary nature of each, why would you want a copy that works like a clone?

Well, I thought about copy() because it's there and it's public.   (Reminder:  AnyRef.clone() is protected by default)

If case classes implemented Clonable and provided a public clone() method I would be a happy camper.  Any chance of this happening?

alex




--
Daniel C. Sobral

I travel to the future all the time.
boisvert
Joined: 2009-11-11,
User offline. Last seen 38 weeks 5 days ago.
Re: Abstracting on copy() method
I didn't state or imply that case classes need a clone() method. 

I believe mutable case classes can be useful and in the settings where they are used a clone() method would be equally convenient.  (Bear in mind that I'm not discounting the value of immutable case classes)

So my proposal would be to have case classes extend a trait similar in spirit to,

package scala

trait Cloneable[T] extends java.lang.Clonable { self: T =>
  override def clone(): T = super.clone().asInstanceOf[T]
}

alex


On Wed, Mar 10, 2010 at 12:14 PM, Daniel Sobral <dcsobral [at] gmail [dot] com> wrote:
Case classes don't _need_ a clone method in their normal usage. So, if you need clone, then you are likely doing something that's unusual and, therefore, difficult to write a clone for in an automated fashion. In fact, technically impossible, given the unknowns.

On Wed, Mar 10, 2010 at 2:54 PM, Alex Boisvert <alex [dot] boisvert [at] gmail [dot] com> wrote:
On Wed, Mar 10, 2010 at 9:14 AM, Daniel Sobral <dcsobral [at] gmail [dot] com> wrote:
Copy is really intended to create new instances of immutable objects with something changed. Clone is intended ot create identical instances of mutable objects. Given the almost complementary nature of each, why would you want a copy that works like a clone?

Well, I thought about copy() because it's there and it's public.   (Reminder:  AnyRef.clone() is protected by default)

If case classes implemented Clonable and provided a public clone() method I would be a happy camper.  Any chance of this happening?

alex




--
Daniel C. Sobral

I travel to the future all the time.

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland