Why isn't opAssign overloadable for classes? - operator-overloading

This D specification table says that assignment overloading is only possible for structs, not classes. This surprises me. Isn't the syntactic sugar of A = B harmless? What was the design rationale for restricting it to structs?

In D, classes are used by reference. So, when you do A = B, you do not copy the object itself, but just a reference to that object.
None of objects are modified during the process. So it makes no sense to define opAssign for thoses.

D classes have reference semantics. If you want a way to get a copy of the object (it think) the standard or conventional thing to do is provide a .dup property.

I would file a bug, and did. The general rule is to follow The D Programming Language by Andrei Alexandrescu, the DMD implementation, and then the website. As I don't have a copy of The D Programming Language handy, I'm going with the DMD implementation on this:
class A {
int a;
string b;
float c;
void opAssign(B b) {
a = b.a;
}
}
class B {
int a;
}
void main()
{
auto a = new A();
a.a = 5;
auto b = new B();
b.a = 10;
a = b;
assert(a.a == 10);
}

Related

Scala var best practice - Encapsulation

I'm trying to understand what's the best practice for using vars in scala, for example
class Rectangle() {
var x:Int = 0
}
Or something like:
class Rectangle() {
private var _x:Int = 0
def x:Int = _x
def x_(newX:Int):Unit = _x=newX
}
Which one can be considered as better? and why?
Thank you!
As Luis already explained in the comment, vars are something that should be avoided whenever you are able to avoid it, and such a simple case like you gave is one of those that can be better designed using something like this:
// Companion object is not necessary in your case
object Rectangle {
def fromInt(x: Int): Option[Rectangle] = {
if(x > 0) {
Some(Rectangle(x))
} else None
}
final case class Rectangle(x: Int)
It would be very rare situations when you can't avoid using vars in scala. Scala general idiom is: "Make your variables immutable, unless there is a good reason not to"
I'm trying to understand what's the best practice for using vars in scala, […]
Best practice is to not use vars at all.
Which one can be considered as better? and why?
The second one is basically equivalent to what the compiler would generate for the first one anyway, so it doesn't really make sense to use the second one.
It would make sense if you wanted to give different accessibility to the setter and the getter, something like this:
class Rectangle {
private[this] var _x = 0
def x = _x
private def x_=(x: Int) = _x = x
}
As you can see, I am using different accessibility for the setter and the getter, so it makes sense to write them out explicitly. Otherwise, just let the compiler generate them.
Note: I made a few other changes to the code:
I changed the visibility of the _x backing field to private[this].
I changed the name of the setter to x_=. This is the standard naming for setters, and it has the added advantage that it allows you to use someRectangle.x = 42 syntactic sugar to call it, making it indistinguishable from a field.
I added some whitespace to give the code room to breathe.
I removed some return type annotations. (This one is controversial.) The community standard is to always annotate your return types in public interfaces, but in my opinion, you can leave them out if they are trivial. It doesn't really take much mental effort to figure out that 0 has type Int.
Note that your first version can also be simplified:
class Rectangle(var x: Int = 0)
However, as mentioned in other answers, you really should make your objects immutable. It is easy to create a simple immutable data object with all the convenience functions generated automatically for you by using a case class:
final case class Rectangle(x: Int = 0)
If you now want to "change" your rectangle, you instead create a new one which has all the properties the same except x (in this case, x is the only property, but there could be more). To do this, Scala generates a nifty copy method for you:
val smallRectangle = Rectangle(3)
val enlargedRectangle = smallRectangle.copy(x = 10)

What's a clean way to check for an objects type?

I want to make a distinction in my code based on the type of an object.
What is a clean (and performant) way to accomplish that?
My object will either be an instance of class A,B or C. All of them extend a class S.
if (obj instanceof A) {...}
Would be what I do in plain java. Is this also good in GWT (or JavaScript at the end)?
Basically the answer is yes if you have declarations like this,
S objA = new A();
S objB = new B();
S objC = new C();
if(objA instacneofc A) //true
if(objB instacneofc A) //false
if(objC instacneofc C) //true

Member-wise assignment in scala?

Does scala support memberwise assignment?
Given:
case class C(var x:Int, var y:Int)
val c = C(1,2)
val d = C(3,4)
is there an operator to assign each member of d to c.
In C/C++ you would have:
struct C{ int x, int y)
C c = {1,2}
C d = {3,4}
c = d
edit1
One of the great benefits of member-wise assignment is that its automatic, in
Both
c() = d
and
c.copyFrom( d )
both suffer from a maintenance problem - if new members are added members to C its easy to overlook adding the member to the user-created function. What's really desired is automated way to copy these values.
edit2
Another use case for this behavior:
val props:ThirdPartyType = ThirdPartyLibrary.getProperties()
val myprops:ThirdPartyType = MyLibrary.loadPropertiesFromFile()
props #= myprops // magic member-wise assignment
Here we may find:
We're stuck with ThirdPartyLibrary and ThirdPartyType (can't change it)
The library doesn't provide the ability to reassign the property object.
The library does provide the ability to assign the property's values. It behaves as a JavaBean POJO with public members.
I can do:
props.a = myprops.a
props.b = myprops.b
...
but this pattern break when we update to V2 of the ThirdParty library. ThirdPartyType has gained new members that we didn't not copy.
Can't this be solved through reflection?
The enhancement is easy:
scala> :pa
// Entering paste mode (ctrl-D to finish)
case class C(var x:Int, var y:Int)
val c = C(1,2)
val d = C(3,4)
// Exiting paste mode, now interpreting.
defined class C
c: C = C(1,2)
d: C = C(3,4)
scala> implicit class CUpdater(val c: C) { def update(d: C) = { c.x=d.x ; c.y=d.y } }
defined class CUpdater
scala> c() = d
scala> c
res1: C = C(3,4)
Usual caveats around mutability apply. And you didn't hear it from me.
This will get you a separate object with all case class constructor arguments copied over, although it will not change the original object that d pointed to:
d = c.copy()
If you really want to modify the original object that d points to (perhaps because you have a reference to it somewhere else - think of pointers to structs in the C programming language), then I think you would have to do something fancy with metaprogramming (i.e. reflection or macros) to get a general solution for this.
But I recommend programming with immutable vals, almost always! If you can live with that, copy is fine.

How to deep copy classes with traits mixed in

Here's some sample scala code.
abstract class A(val x: Any) {
abstract def copy(): A
}
class b(i: Int) extends A(i) {
override def copy() = new B(x)
}
class C(s: String) extends A(s) {
override def copy() = new C(x)
}
//here's the tricky part
Trait t1 extends A {
var printCount = 0
def print = {
printCount = printCount + 1
println(x)
}
override def copy = ???
}
Trait t2 extends A {
var doubleCount = 0
def doubleIt = {
doubleCount = doubleCount + 1
x = x+x
}
override def copy = ???
}
val q1 = new C with T1 with T2
val q2 = new B with T2 with T1
OK, as you've likely guessed, here's the question.
How can I implement copy methods in T1 and T2, such that weather they are mixed in with B, C, or t2/t1, I get a copy of the whole ball of wax?
for example, q2.copy should return a new B with T2 with T1, and q1.copy should return a new C with T1 with T2
Thanks!
Compositionality of object construction
The basic problem here is, that, in Scala as well as in all other languages I know, object construction doesn't compose. Consider two abstract operations op1 and op2, where op1 makes property p1 true and where op2 makes property p2 true. These operations are composable with respect to a composition operation ○, if op1 ○ op2 makes both p1 and p2 true. (Simplified, properties also need a composition operation, for example conjunction such as and.)
Let's consider the new operation and the property that new A(): A, that is, an object created by calling new A is of type A. The new operation lacks compositionality, because there is no operation/statement/function f in Scala that allows you to compose new A and new B such that f(new A, new B): A with B. (Simplified, don't think too hard about whether A and B must be classes or traits or interfaces or whatever).
Composing with super-calls
Super-calls can often be used to compose operations. Consider the following example:
abstract class A { def op() {} }
class X extends A {
var x: Int = 0
override def op() { x += 1 }
}
trait T extends A {
var y: String = "y"
override def op() { super.op(); y += "y" }
}
val xt = new X with T
println(s"${xt.x}, ${xt.y}") // 0, y
xt.op()
println(s"${xt.x}, ${xt.y}") // 1, yy
Let X.op's property be "x is increased by one" and let T.op's property be "y's length is increased by one". The composition achieved with the super-call fulfils both properties. Hooooray!
Your problem
Let's assume that you are working with a class A which has a field x, a trait T1 which has a field y and another trait T2 which has a field z. What you want is the following:
val obj: A with T1 with T2
// update obj's fields
val objC: A with T1 with T2 = obj.copy()
assert(obj.x == objC.x && obj.y == objC.y && obj.z == objC.z)
Your problem can be divided into two compositionality-related sub-problems:
Create a new instance of the desired type. This should be achieved by a construct method.
Initialise the newly created object such that all its fields have the same values (for brevity, we'll only work with value-typed fields, not reference-typed ones) as the source object. This should be achieved by a initialise method.
The second problem can be solved via super-calls, the first cannot. We'll consider the easier problem (the second) first.
Object initialisation
Let's assume that the construct method works as desired and yields an object of the right type. Analogous to the composition of the op method in the initial example we could implement initialise such that each class/trait A, T1 and T2 implements initialise(objC) by setting the fields it knows about to the corresponding values from this (individual effects), and by calling super.initialise(objC) in order to compose these individual effects.
Object creation
As far as I can see, there is no way to compose object creation. If an instance of A with T1 with T2 is to be created, then the statement new A with T1 with T2 must be executed somewhere. If super-calls could help here, then something like
val a: A = new A // corresponds to the "deepest" super-call
val at1: A with T1 = a with new T1
would be necessary.
Possible solutions
I implemented a solution (see this gist) based on abstract type members and explicit mixin classes (class AWithT1WithT2 extends A with T1 with T2; val a = new AWithT1WithT2 instead of val a = new A with T1 with T2). It works and it is type-safe, but it is neither particularly nice nor concise. The explicit mixin classes are necessary, because the construct method of new A with T1 with T2 must be able to name the type it creates.
Other, less type-safe solutions are probably possible, for example, casting via asInstanceOf or reflection. I haven't tried something along those lines, though.
Scala macros might also be an option, but I haven't used them yet and thus don't know enough about them. A compiler plugin might be another heavy-weight option.
That is one of the reasons, why extending case classes is deprecated. You should get a compiler warning for that. How should the copy method, that is defined in A, know, that there may also be a T or whatever? By extending the case class,
you break all the assumptions, that the compiler made, when generating methods like equals, copy and toString.
The easiest and simplest answer is to make your concrete types into case classes. Then you get the compiler-supplied copy method which accepts named parameters for all the class's constructor parameters so you can selectively differentiate the new value from the original.

What is this Scala syntax called: new C { i = 5 } // there's a block after the new

I encountered this syntax in someone else's Scala code, and don't remember reading about it:
val c = new C { i = 5 }
It appears that the block after the new C is equivalent to:
val c = new C
c.i = 5
assuming a class definition like:
class C {
var ii = 1
def i_=(v: Int) { ii = v }
def i = ii
}
What is this syntax called in Scala? I want to read more about it, but I can't find it described in Programming in Scala or elsewhere.
You are instantiating an anonymous subclass of C.
It is not equivalent to the code you've shown — try calling getClass on the two instances called c in your snippets.