digitalmars.D.learn - I don't get it. version(unittest) can't seem to use local variable
- dysmondad (38/38) Jul 11 2014 I'm new to D. I've been using C since it was a baby and C++ back
- Rikki Cattermole (12/48) Jul 11 2014 try:
- dysmondad (5/17) Jul 12 2014 Thank you very much. That was quite helpful.
- Rikki Cattermole (12/30) Jul 12 2014 Basically, have a function that does something like string manipulation
- dysmondad (4/7) Jul 12 2014 Thanks for the link and the information.
- H. S. Teoh via Digitalmars-d-learn (17/20) Jul 12 2014 Just include unittest blocks in your program and compile with -unittest.
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (6/9) Jul 11 2014 Unrelated to your question, you want to return just Velocity there.
- dysmondad (6/16) Jul 12 2014 Right you are. I knew that but it still didn't translate into
- H. S. Teoh via Digitalmars-d-learn (20/43) Jul 12 2014 ref makes it possible for the caller to modify the pointer returned by
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (15/31) Jul 12 2014 The twist here is that the OP's function returned 'this' by reference.
- H. S. Teoh via Digitalmars-d-learn (7/45) Jul 12 2014 [...]
- H. S. Teoh via Digitalmars-d-learn (10/32) Jul 12 2014 [...]
I'm new to D. I've been using C since it was a baby and C++ back when it was only a pre-compiler for c. So, I may just be stuck thinking in C land. The issue is I am attempting to use the version(unittest) feature. However the compiler pukes up the error below. I'm sure it's something easy enough but I've not been able to find any help in Google land. I don't know if I have the opOpAssign defined correctly or if there's something wrong with the constructor or both. dysmondad Julep:~/src/D$ gdc -c velocity.d velocity.d:110: error: no identifier for declarator v velocity.d:110: error: semicolon expected, not '*=' velocity.d:110: error: Declaration expected, not '*=' class Velocity { private: float _Y = 0.0; float _X = 0.0; public: this (float x, float y ) { _Y = y; _X = x; } ref Velocity opOpAssign(string op) ( in float multiplier ) if( op == "*" ) { _Y *= multiplier; _X *= multiplier; return this; } } version(unittest) { Velocity v = new Velocity( 2.0f, 5.0f ); v *= 5.0f; // <- line 110 printf( "v = %s\n", to!string(v) ); }
Jul 11 2014
On 12/07/2014 5:08 p.m., dysmondad wrote:I'm new to D. I've been using C since it was a baby and C++ back when it was only a pre-compiler for c. So, I may just be stuck thinking in C land. The issue is I am attempting to use the version(unittest) feature. However the compiler pukes up the error below. I'm sure it's something easy enough but I've not been able to find any help in Google land. I don't know if I have the opOpAssign defined correctly or if there's something wrong with the constructor or both. dysmondad Julep:~/src/D$ gdc -c velocity.d velocity.d:110: error: no identifier for declarator v velocity.d:110: error: semicolon expected, not '*=' velocity.d:110: error: Declaration expected, not '*=' class Velocity { private: float _Y = 0.0; float _X = 0.0; public: this (float x, float y ) { _Y = y; _X = x; } ref Velocity opOpAssign(string op) ( in float multiplier ) if( op == "*" ) { _Y *= multiplier; _X *= multiplier; return this; } } version(unittest) { Velocity v = new Velocity( 2.0f, 5.0f ); v *= 5.0f; // <- line 110 printf( "v = %s\n", to!string(v) ); }try: unittest { Velocity v = new Velocity( 2.0f, 5.0f ); v *= 5.0f; // <- line 110 printf( "v = %s\n", to!string(v) ); } instead. Basically version is like static if, it doesn't indicate its a function. Instead it changes what code gets compiled. Where as a unittest block, is essentially just a function that gets called at a special time, that is only compiled as if version(unittest) was also used.
Jul 11 2014
.....try: unittest { Velocity v = new Velocity( 2.0f, 5.0f ); v *= 5.0f; // <- line 110 printf( "v = %s\n", to!string(v) ); } instead. Basically version is like static if, it doesn't indicate its a function. Instead it changes what code gets compiled. Where as a unittest block, is essentially just a function that gets called at a special time, that is only compiled as if version(unittest) was also used.Thank you very much. That was quite helpful. So, what is the generally accepted way include unit testing? TDD is all the rage these days and I though I would try my hand at it as well as D.
Jul 12 2014
On 13/07/2014 2:35 p.m., dysmondad wrote:.....Basically, have a function that does something like string manipulation or complex math? Use a unittest block for it. Which you can do before you write the function. It may not compile however. Also do note, assert's are part of the language. And will cause an exception to throw should the expression return false. assert(exp, "description"); Description is optional however. Here's an example https://github.com/rikkimax/skeleton/blob/master/source/skeleton/syntax/download_mkdir.d#L175 Of course there will be better ones, just something I was doing last night however.try: unittest { Velocity v = new Velocity( 2.0f, 5.0f ); v *= 5.0f; // <- line 110 printf( "v = %s\n", to!string(v) ); } instead. Basically version is like static if, it doesn't indicate its a function. Instead it changes what code gets compiled. Where as a unittest block, is essentially just a function that gets called at a special time, that is only compiled as if version(unittest) was also used.Thank you very much. That was quite helpful. So, what is the generally accepted way include unit testing? TDD is all the rage these days and I though I would try my hand at it as well as D.
Jul 12 2014
...https://github.com/rikkimax/skeleton/blob/master/source/skeleton/syntax/download_mkdir.d#L175 Of course there will be better ones, just something I was doing last night however.Thanks for the link and the information. That's looks like what I need so I'm going to rip off your code example. :)
Jul 12 2014
On Sun, Jul 13, 2014 at 02:35:11AM +0000, dysmondad via Digitalmars-d-learn wrote: [...]So, what is the generally accepted way include unit testing? TDD is all the rage these days and I though I would try my hand at it as well as D.Just include unittest blocks in your program and compile with -unittest. Example: unittest { assert(myNewFunc(1,2,3) == 456); ... // whatever else to verify it } auto myNewFunc(int x, int y, int z) { ... // code here } The program will run all unittests on startup before main() executes, so you can just run it as usual. If any unittests fail it will abort with an error message. T -- What's a "hot crossed bun"? An angry rabbit.
Jul 12 2014
On 07/11/2014 10:08 PM, dysmondad wrote:class Velocity {[...]ref Velocity opOpAssign(string op) ( in float multiplier )Unrelated to your question, you want to return just Velocity there. Unlike C++, classes are reference types in D. So, Velocity itself is essentially a Velocity* in C++. Ali
Jul 11 2014
On Saturday, 12 July 2014 at 05:23:29 UTC, Ali Çehreli wrote:On 07/11/2014 10:08 PM, dysmondad wrote:Right you are. I knew that but it still didn't translate into code. Thank you for pointing that out. I guess eventually I will remember that class variables are pointers. As a point of curiosity, is the ref keyword in this case simply redundant or does it actually make a difference?class Velocity {[...]ref Velocity opOpAssign(string op) ( in float multiplier) Unrelated to your question, you want to return just Velocity there. Unlike C++, classes are reference types in D. So, Velocity itself is essentially a Velocity* in C++. Ali
Jul 12 2014
On Sun, Jul 13, 2014 at 02:39:00AM +0000, dysmondad via Digitalmars-d-learn wrote:On Saturday, 12 July 2014 at 05:23:29 UTC, Ali Çehreli wrote:ref makes it possible for the caller to modify the pointer returned by the callee. For example: class D { int x; } class C { D d; this(D _d) { d = _d; } ref D getPtr() { return d; } } auto d1 = new D; auto d2 = new D; auto c = new C(d1); // c.d now points to d1 assert(c.getPtr() is d1); // getPtr returns d1 c.getPtr() = d2; // this modifies c.d assert(c.getPtr() is d2); // getPtr now returns d2 If you do not wish the caller to do this, remove the ref from the function signature. T -- Don't drink and derive. Alcohol and algebra don't mix.On 07/11/2014 10:08 PM, dysmondad wrote:Right you are. I knew that but it still didn't translate into code. Thank you for pointing that out. I guess eventually I will remember that class variables are pointers. As a point of curiosity, is the ref keyword in this case simply redundant or does it actually make a difference?class Velocity {[...]ref Velocity opOpAssign(string op) ( in float multiplier) Unrelated to your question, you want to return just Velocity there. Unlike C++, classes are reference types in D. So, Velocity itself is essentially a Velocity* in C++. Ali
Jul 12 2014
On 07/12/2014 08:37 PM, H. S. Teoh via Digitalmars-d-learn wrote:ref makes it possible for the caller to modify the pointer returned by the callee. For example: class D { int x; } class C { D d; this(D _d) { d = _d; } ref D getPtr() { return d; } } auto d1 = new D; auto d2 = new D; auto c = new C(d1); // c.d now points to d1 assert(c.getPtr() is d1); // getPtr returns d1 c.getPtr() = d2; // this modifies c.d assert(c.getPtr() is d2); // getPtr now returns d2 If you do not wish the caller to do this, remove the ref from the function signature.The twist here is that the OP's function returned 'this' by reference. Changing that not only not have any effect on the object, it would also be undefined behavior because 'this' is a local variable in that use. class C { ref C getPtr() { return this; } } void main() { auto c = new C(); assert(c.getPtr() is c); c.getPtr() = new C(); // modifying dead variable assert(c.getPtr() is c); // no effect } Ali
Jul 12 2014
On Sat, Jul 12, 2014 at 09:20:06PM -0700, Ali Çehreli via Digitalmars-d-learn wrote:On 07/12/2014 08:37 PM, H. S. Teoh via Digitalmars-d-learn wrote:[...] Hmm. Shouldn't this be a compiler bug?? Returning a ref to a local variable should be illegal, even implicit ones like 'this'. T -- If you want to solve a problem, you need to address its root cause, not just its symptoms. Otherwise it's like treating cancer with Tylenol...ref makes it possible for the caller to modify the pointer returned by the callee. For example: class D { int x; } class C { D d; this(D _d) { d = _d; } ref D getPtr() { return d; } } auto d1 = new D; auto d2 = new D; auto c = new C(d1); // c.d now points to d1 assert(c.getPtr() is d1); // getPtr returns d1 c.getPtr() = d2; // this modifies c.d assert(c.getPtr() is d2); // getPtr now returns d2 If you do not wish the caller to do this, remove the ref from the function signature.The twist here is that the OP's function returned 'this' by reference. Changing that not only not have any effect on the object, it would also be undefined behavior because 'this' is a local variable in that use. class C { ref C getPtr() { return this; } } void main() { auto c = new C(); assert(c.getPtr() is c); c.getPtr() = new C(); // modifying dead variable assert(c.getPtr() is c); // no effect }
Jul 12 2014
On Sat, Jul 12, 2014 at 09:30:44PM -0700, H. S. Teoh via Digitalmars-d-learn wrote:On Sat, Jul 12, 2014 at 09:20:06PM -0700, Ali Çehreli via Digitalmars-d-learn wrote:[...][...] Filed as bug: https://issues.dlang.org/show_bug.cgi?id=13116 It's pretty serious, since it causes memory corruption. In fact, it also breaks safe-ty (see second bug note in above link). T -- The early bird gets the worm. Moral: ewww...The twist here is that the OP's function returned 'this' by reference. Changing that not only not have any effect on the object, it would also be undefined behavior because 'this' is a local variable in that use. class C { ref C getPtr() { return this; } } void main() { auto c = new C(); assert(c.getPtr() is c); c.getPtr() = new C(); // modifying dead variable assert(c.getPtr() is c); // no effect }[...] Hmm. Shouldn't this be a compiler bug?? Returning a ref to a local variable should be illegal, even implicit ones like 'this'.
Jul 12 2014