www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - "Elementary, dear Watson... you're an idiot"

reply ajvincent juno.com writes:
I'm doing something wrong here, and I don't quite know what.

Just to simplify, in D it looks like:

class Foo {
public byte x = 2;
}

Foo a = new Foo();
Foo b = new Foo();
a.x = 3;
writef(b.x) // returns 3;

The equivalent in JavaScript is:

function Foo() {
}
Foo.prototype = {
x: 2
};

var a = new Foo();
var b = new Foo();
a.x = 3;
alert(b.x); // returns 3

What I want (in JavaScript) is:

function Foo() {
this.x = 2;
}

var a = new Foo();
var b = new Foo();
a.x = 3;
alert(b.x) // returns 2

Unfortunately, the D spec doesn't make clear what I'm supposed to be doing.
Likewise, dsource.org didn't seem to have a tutorial showing what the correct
answer is.

Also, the operator overloading page is obscure when it comes to opEquals and
opCmp... specifically, it doesn't say what a class's opCmp should return under
what conditions.
Sep 27 2004
next sibling parent J C Calvarese <jcc7 cox.net> writes:
ajvincent juno.com wrote:
 I'm doing something wrong here, and I don't quite know what.
I'll try to offer some suggestions.
 
 Just to simplify, in D it looks like:
 
 class Foo {
 public byte x = 2;
 }
 
 Foo a = new Foo();
 Foo b = new Foo();
 a.x = 3;
 writef(b.x) // returns 3;
Try this (it works for me): import std.stdio; class Foo { public byte x = 2; } void main() { Foo a = new Foo(); Foo b = new Foo(); a.x = 3; writefln(b.x); } My output: "2" I don't know what you did wrong. Obviously (since the code you provided above doesn't even compile), you didn't just cut-and-paste what you tried.
 
 The equivalent in JavaScript is:
 
 function Foo() {
 }
 Foo.prototype = {
 x: 2
 };
 
 var a = new Foo();
 var b = new Foo();
 a.x = 3;
 alert(b.x); // returns 3
 
 What I want (in JavaScript) is:
 
 function Foo() {
 this.x = 2;
 }
 
 var a = new Foo();
 var b = new Foo();
 a.x = 3;
 alert(b.x) // returns 2
If you want a more complicated example (using properties), you could also write it in D like this: import std.stdio; /* for writefln */ class Foo { public: this() { m_x = 2; } /* 'get' and 'set' properties: http://www.digitalmars.com/d/property.html */ /* read ('get') property */ int x() { return m_x; } /* write ('set') property */ int x(int value) { return m_x = value; } private: int m_x; } void main() { Foo a = new Foo(); Foo b = new Foo(); a.x = 3; writefln(b.x); }
 
 Unfortunately, the D spec doesn't make clear what I'm supposed to be doing.
Try reading the spec again. It didn't start making sense to me until I read it for the 3rd or 4th time. ;)
 Likewise, dsource.org didn't seem to have a tutorial showing what the correct
 answer is.
The tutorial is very much a "work-in-progress". -- Justin (a/k/a jcc7) http://jcc_7.tripod.com/d/
Sep 27 2004
prev sibling next sibling parent reply Stewart Gordon <Stewart_member pathlink.com> writes:
In article <cjatak$1sp1$1 digitaldaemon.com>, ajvincent juno.com 
says...
<snip>
 Also, the operator overloading page is obscure when it comes to 
 opEquals and opCmp...  specifically, it doesn't say what a class's 
 opCmp should return under what conditions.
Indeed, it expects you to be able to work it out from what it does tell you about them. Specifically: a.opEquals(b) != 0 for a == b a.opEquals(b) == 0 for a != b a.opCmp(b) < 0 for a < b a.opCmp(b) > 0 for a > b a.opcmp(b) == 0 for !(a < b || a > b) Stewart.
Sep 28 2004
parent reply ajvincent <ajvincent_member pathlink.com> writes:
Indeed, it expects you to be able to work it out from what it does 
tell you about them.

Specifically:

a.opEquals(b) != 0   for   a == b
a.opEquals(b) == 0   for   a != b
a.opCmp(b) < 0       for   a < b
a.opCmp(b) > 0       for   a > b
a.opcmp(b) == 0      for   !(a < b || a > b)

Stewart.
Hm. That last option answers something I was greatly concerned about. Namely, how should I handle a(opCmp(NaN))...
Sep 28 2004
next sibling parent reply Sean Kelly <sean f4.ca> writes:
In article <cjch2j$2rui$1 digitaldaemon.com>, ajvincent says...
a.opCmp(b) < 0       for   a < b
a.opCmp(b) > 0       for   a > b
a.opcmp(b) == 0      for   !(a < b || a > b)
Hm. That last option answers something I was greatly concerned about. Namely, how should I handle a(opCmp(NaN))...
How does D handle comparisons between floating point primitives where one is NaN? I would mimic this behavior. Sean
Sep 28 2004
parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <cjcimp$2spj$1 digitaldaemon.com>, Sean Kelly says...

How does D handle comparisons between floating point primitives where one is
NaN? 
It doesn't use opCmp(). opCmp() is for objects, not primatives (although one can use it to compare an object /with/ a primitive, if such a comparison makes sense).
I would mimic this behavior.
It is not possible to mimic the behavior of float or complex primatives in an object, because opCmp() just is not powerful enough (it doesn't handle the cases <>= or !<>=). I remember suggesting a while back that opCmp() should be modified to return an enum { LESS, EQUAL, GREATER, INCOMPARABLE }, but few people liked the idea, and it sort of got lost in another "why does Object define opCmp() anyway?" thread. Arcane Jill
Sep 28 2004
parent Burton Radons <burton-radons smocky.com> writes:
Arcane Jill wrote:
 In article <cjcimp$2spj$1 digitaldaemon.com>, Sean Kelly says...
 
[snip]
I would mimic this behavior.
It is not possible to mimic the behavior of float or complex primatives in an object, because opCmp() just is not powerful enough (it doesn't handle the cases <>= or !<>=).
You can with a value type if you return float from opCmp: bit opEquals (Type other) { return opCmp (other) == 0; } float opCmp (Type other) { if (value < other.value) return -1; if (value > other.value) return +1; if (value == other.value) return 0; return float.nan; } That'll work correctly for all comparisons (yes, I tested). So all Object.opCmp needs is to return float.
Sep 29 2004
prev sibling parent "Ben Hinkle" <bhinkle mathworks.com> writes:
"ajvincent" <ajvincent_member pathlink.com> wrote in message
news:cjch2j$2rui$1 digitaldaemon.com...
Indeed, it expects you to be able to work it out from what it does
tell you about them.

Specifically:

a.opEquals(b) != 0   for   a == b
a.opEquals(b) == 0   for   a != b
a.opCmp(b) < 0       for   a < b
a.opCmp(b) > 0       for   a > b
a.opcmp(b) == 0      for   !(a < b || a > b)

Stewart.
Hm. That last option answers something I was greatly concerned about.
Namely,
 how should I handle a(opCmp(NaN))...
The table of floating point comparison operators in http://www.digitalmars.com/d/expression.html#RelExpression says for a floating point variable "a" evaluating "a < NaN" throws an exception. So based on that a.opCmp(NaN) should throw an exception (depending on just what your class is doing of course). I don't see a way of overloading the "unordered" operators like !<>= but presumably that will come some day. I don't even know what !<>= does with objects or objects that overload opCmp and/or opEquals. Maybe it just assumes anything overloading opCmp always has a total order.
Sep 28 2004
prev sibling parent reply Toaster <wb sapo.pt> writes:
On Tue, 28 Sep 2004 05:37:24 +0000 (UTC), ajvincent juno.com wrote:

class Foo {
public byte x = 2;
}

Foo a = new Foo();
Foo b = new Foo();
a.x = 3;
writef(b.x) // returns 3;
I compiled this (wrapped in a main()) and for me it actually outputs 2 (as I expected)
Sep 28 2004
parent reply ajvincent <ajvincent_member pathlink.com> writes:
I compiled this (wrapped in a main()) and for me it actually outputs 2
(as I expected)
Hm. For some reason, a test program I wrote on my own also showed the expected behavior. But for my much larger BigDecimal library script, it's unmistakably doing something unexpected. I'll try to reduce all the fluff into a minimum testcase to see what I did wrong. Thanks everyone, though.
Sep 28 2004
parent reply ajvincent <ajvincent_member pathlink.com> writes:
class Foo {
private bit[] bool = [0];

unittest {
Foo a = new Foo;
Foo b = new Foo;
a.bool[0] = 1;
assert(b.bool[0] == 0);
}
}

int main() {
return 0;
}

One is left to wonder if that was a bug on the part of the programmer or not.
Sep 28 2004
parent "Ben Hinkle" <bhinkle mathworks.com> writes:
"ajvincent" <ajvincent_member pathlink.com> wrote in message
news:cjcsp3$15m$1 digitaldaemon.com...
 class Foo {
 private bit[] bool = [0];

 unittest {
 Foo a = new Foo;
 Foo b = new Foo;
 a.bool[0] = 1;
 assert(b.bool[0] == 0);
 }
 }

 int main() {
 return 0;
 }

 One is left to wonder if that was a bug on the part of the programmer or
not. This should be the same issue as for string literals. The field "bool" (confusing name, by the way, given that bool is defined in object.d as an alias for bit) is initialized to have length 1 and data pointer pointing to a shared (read-only on Linux) bit containing 0. To obtain distinct copies one needs to have a constructor that allocates the array: class Foo { private bit[] bool; this() { bool = new bit[1]; } unittest { Foo a = new Foo; Foo b = new Foo; a.bool[0] = 1; assert(b.bool[0] == 0); } } int main() { return 0; }
Sep 29 2004