Re: Constructor params with same name as members
On Thursday, October 23, 2014 11:47:04 Shriramana Sharma via Digitalmars-d-learn wrote: Oh OK here it is: http://dlang.org/deprecate.html#Variable%20shadowing%20inside%20functions But it says "it is an error to use the feature" by 2.061 and I'm using 2.066! Doesn't the scope of that deprecation cover struct members too? In general it should be like "variables in inner scopes should not shadow those in outer scopes" irrespective of what the scopes are, right? Of course, for clarity we could add "except when the inner scope is a separate namespace", so it is made clear that enum/struct/class members do not shadow outer variables... Shadowing is only illegal when you're dealing with local variables both declared within the same function with one in an inner scope. It's perfectly legal when one variable is a local variable and the other is a member variable, class/struct variable, or module-level variable. Having a parameter shadow a member variable is perfectly okay, because you can still reference the member variable via the invisible this parameter. Questions like this have come up and been discussed before, but using the same parameter names as member variable names for constructors is such a common practice that there would be quite a bit of screaming if we didn't allow it. It's not going away, and personally, I'd be very annoyed if it did. It's wonderfully clear when the parameter name has the same name as the member variable that it's going to initialize, and I'd hate to have to come up with different parameter names just because someone was worried about someone being foolish enough to do x = x; which is so obviously wrong that I don't know how much of anyone could make that mistake. But simply making it illegal to assign a variable to itself would solve that problem, and that arguably should be done, since it's a essentially a no-op. Regardless, a lot of people solve it by simply tagging their member variables in some manner to indicate that they're member variables and not local variables - e.g. _x instead of x. - Jonathan M Davis
Re: Constructor params with same name as members
Oh OK here it is: http://dlang.org/deprecate.html#Variable%20shadowing%20inside%20functions But it says "it is an error to use the feature" by 2.061 and I'm using 2.066! Doesn't the scope of that deprecation cover struct members too? In general it should be like "variables in inner scopes should not shadow those in outer scopes" irrespective of what the scopes are, right? Of course, for clarity we could add "except when the inner scope is a separate namespace", so it is made clear that enum/struct/class members do not shadow outer variables... -- Shriramana Sharma ஶ்ரீரமணஶர்மா श्रीरमणशर्मा
Re: Constructor params with same name as members
On Thu, Oct 23, 2014 at 11:01:10AM +0530, Shriramana Sharma via Digitalmars-d-learn wrote: > Hello. I perfectly realize that it's not advisable to take advantage > of shadowing. In fact, I asked the question because I thought D > specifically *didn't* allow shadowing, but here it is, being silently > permitted to mishappen... I seem to read to have read that (D didn't > allow shadowing) but I'm not able to point to where... > > BTW I compiled it with LDC 0.14.0 and separately with D 2.066.0 and > both give the same result. > > So shouldn't the compiler ideally complain about the arguments > shadowing members? [...] File a bug, if one isn't already filed. (I vaguely seem to recall an existing bug to that effect, but I could be wrong.) T -- What do you call optometrist jokes? Vitreous humor.
Re: Why do some language-defined attributes have @ and some not?
On Thu, Oct 23, 2014 at 10:50:07AM +0530, Shriramana Sharma via Digitalmars-d-learn wrote: [...] > So I agree with you that for now this is not an urgent need. I guess > when we clean out all that !> <>= stuff this can be done too, or > something like that... [...] I believe those flying-saucer operators (:-P) are slated for removal. IIRC, Walter has recently actually made some PRs to deprecate those operators, which means in a couple o' releases they should finally be gone for good. T -- Shin: (n.) A device for finding furniture in the dark.
Re: Constructor params with same name as members
Hello. I perfectly realize that it's not advisable to take advantage of shadowing. In fact, I asked the question because I thought D specifically *didn't* allow shadowing, but here it is, being silently permitted to mishappen... I seem to read to have read that (D didn't allow shadowing) but I'm not able to point to where... BTW I compiled it with LDC 0.14.0 and separately with D 2.066.0 and both give the same result. So shouldn't the compiler ideally complain about the arguments shadowing members? -- Shriramana Sharma ஶ்ரீரமணஶர்மா श्रीरमणशर्मा
Re: Why do some language-defined attributes have @ and some not?
On Thursday, 23 October 2014 at 02:22:41 UTC, Jonathan M Davis wrote: On Thursday, 23 October 2014 at 00:59:26 UTC, Shriramana Sharma via Digitalmars-d-learn wrote: LOL. I understand the sentiment, but it's a waste of time. Jonathan, I agree It's impossible to debate such thing with Walter / Andrej right now, but I don't think It's a waste of time: every explicit and accountable opinion about that is a little stone to weigh in the balance. --- /Paolo
Re: Returning a ref to a temporary already possible?
On Thu, Oct 23, 2014 at 10:39:34AM +0530, Shriramana Sharma via Digitalmars-d-learn wrote: > IIUC the whole deal with not allowing ref parameters to point to > rvalues is the fear that they may be returned outside the function, > but it seems this is already possible: > > module reftest ; > import std.stdio ; > struct Pair { > int x, y ; > this (int x_, int y_) { x = x_ ; y = y_ ; writeln("Pair constructed") ; > } > auto handle() { return this ; } > } > void main() { > auto P = Pair(1, 2).handle ; > writeln(typeof(P).stringof) ; > P.x = 3 ; > writeln(P.x, ' ', P.y) ; > } > > Running this makes it clear that only the one Pair object is ever > constructed. But I don't understand how it is that the type of P is > Pair and not ref(Pair). [...] ref is a storage class, not a type constructor. There is actually no such type as ref(Pair). The 'ref' applies only to the function parameter (or return value), NOT to whatever it gets assigned to. T -- Microsoft is to operating systems & security ... what McDonalds is to gourmet cooking.
Re: Why do some language-defined attributes have @ and some not?
On 10/23/14, Jonathan M Davis via Digitalmars-d-learn wrote: > So, yes, we do have historical baggage, albeit nowhere near as > much as C++ does. OK understood, but I may just go and file that bug so that if there is a future D 3 series, then stuff like this can be cleaned up. :-) I'm finicky like that! ;-) > Walter and Andrei very much want D to be being used in production > at this point, We all do, no? Not only those two! :-) So I agree with you that for now this is not an urgent need. I guess when we clean out all that !> <>= stuff this can be done too, or something like that... -- Shriramana Sharma ஶ்ரீரமணஶர்மா श्रीरमणशर्मा
Re: Constructor params with same name as members
On Thu, Oct 23, 2014 at 10:33:53AM +0530, Shriramana Sharma via Digitalmars-d-learn wrote: > Hello. Please see the following code: > > import std.stdio ; > struct Pair { > int x, y ; > this (int x, int y) { x = x ; y = y ; } Please don't write code like this. How is the compiler supposed to know that "x = x" is supposed to mean "this.x = x", as opposed to "x = x" or "this.x = this.x" or "x = this.x"??! I used to enjoy writing this kind of code by cleverly exploiting subtle differences in symbol lookup rules, but eventually I realized that this kind of coding style is riddled with subtle errors, because shadowing member variables can lead to nasty mistakes (writing 'x' in your member functions can sometimes mean this.x, sometimes a function parameter or local variable) and makes the code unmaintainable (anybody else reading the code may not be aware of the subtle lookup rules you're exploiting to make the code work) and fragile (code changes like adding/removing a local variable may inadvertently change the meaning of 'x' in another line of code). Generally, shadowing member variables with parameter names is a Bad Idea(tm). Instead, my advice is to adopt a naming convention to distinguish between them, e.g.: struct S { int x, y; this(int _x, int _y) { x = _x; // now no longer ambiguous y = _y; } } T -- Don't modify spaghetti code unless you can eat the consequences.
Re: Using in as a parameter qualifier
Hi Jonathan and thanks again for your kind replies. On 10/23/14, Jonathan M Davis via Digitalmars-d-learn wrote: > That will result in a move operation. No copying will take place. > And it technically, it may not actually move anything it all and > just use the object where it's initially constructed. I'm not > sure what the actual, generated machine code ends up doing in > that regard. But there's no copying or double-construction. Well blitting is copying isn't it? I read your SE answer where you define a move as a blit without the postblit. Hmm. Somehow the name "move" seems to be misleading... To clarify that, is this the same as the C++11 move behaviour or is it subtly different? IIUC in case of a C++ vector, a move would mean that the length and possibly other direct members of the class including the pointer to the heap-allocated managed data would be copied to the target (same as blit I guess) and the managed data itself is not dupped (i.e. postblit is not called) and we call it a move, yeah? But it's actually better called a shallow copy, no? Or is a shallow copy different from a move in any other way? > const does _not_ mean that a copy doesn't need to be made. It has > zero effect on that. In fact, if you're passing an lvaue to a > function that doesn't take its arguments by ref, it's almost a > guarantee that a copy will be made. The only exception would be > if the compiler determines that the lvalue in question is never > used after that call, in which case, it might just move the > object rather than copy it. But that doesn't seem logical. If the compiler is able to determine that the lvalue in question is not modified in the function at all (either heuristically or by the programmer defining it as "in" or "const") then it should be able to optimize by not even making the move aka shallow copy, no? Of course I understand it doesn't *have* to do an optimization, and that D believes that ideally optimization opportunities should be recognized and acted upon by the compiler and the user should not need to specify places where this is possible (I listened to the Andrei/Walter panel talk where IIUC they were saying this is the ideal behaviour and keywords like "pure" "nothrow" etc shouldn't ideally be needed), but I just want to be sure whether I'm understanding right that there is indeed the possibility in the present case. > So, you mean if draw was a member function of Bezier, and you did > something like > Bezier(100, 100, 133, 200, 166, 200, 200, 200).draw() > you want to know whether a copy of the Bezier object would be > made? The this member of a struct is a ref - in this case ref > Bezier - so it doesn't make a copy. Actually it doesn't even make a move aka shallow copy right? If that's right, then sorta here we are seeing how a ref to a temporary can indeed exist, i.e. implicitly within the member functions. (I'll post separately on that topic.) > If draw is a free function, then > Bezier(100, 100, 133, 200, 166, 200, 200, 200).draw() > is literally transformed into > draw(Bezier(100, 100, 133, 200, 166, 200, 200, 200)) > by the compiler, so the behavior of those two lines is identical. > And as I said above, that means that a move is made. OK so if I read this right, if the function is defined as a free function, then calling it on a temporary will make a shallow copy (and I can't use an explicit ref on the temporary argument), but if it is defined as a member then calling it on a temporary will not even make a shallow copy. Because of UFCS, how I'm *calling* the function will not have an effect on whether the shallow copy is made or not, but how I *defined* it will. Correct? > I'm not sure why it would sound presumptious if you're asking > whether you're understanding or guesses about how D works are > wrong. Questions are certainly welcome. That's very nice of you. I only added the advance apology because sometimes some friends of mine have commented that I come across high and mighty in saying "this should be like this and this and not like that" in technical fora where people more knowledgeable than me exist. As Andrei said in his opening address, it's nice to see that one big strength of D is the patient and friendly replies of the D community. :-) -- Shriramana Sharma ஶ்ரீரமணஶர்மா श्रीरमणशर्मा
Returning a ref to a temporary already possible?
IIUC the whole deal with not allowing ref parameters to point to rvalues is the fear that they may be returned outside the function, but it seems this is already possible: module reftest ; import std.stdio ; struct Pair { int x, y ; this (int x_, int y_) { x = x_ ; y = y_ ; writeln("Pair constructed") ; } auto handle() { return this ; } } void main() { auto P = Pair(1, 2).handle ; writeln(typeof(P).stringof) ; P.x = 3 ; writeln(P.x, ' ', P.y) ; } Running this makes it clear that only the one Pair object is ever constructed. But I don't understand how it is that the type of P is Pair and not ref(Pair). -- Shriramana Sharma ஶ்ரீரமணஶர்மா श्रीरमणशर्मा
Constructor params with same name as members
Hello. Please see the following code: import std.stdio ; struct Pair { int x, y ; this (int x, int y) { x = x ; y = y ; } } void main() { auto P = Pair(1, 2) ; writeln(P.x, ' ', P.y) ; } This outputs 0 0, whereas the equivalent C++ code outputs 1 2 correctly: # include struct Pair { int x, y ; Pair(int x, int y) : x(x), y(y) {} } ; int main() { auto P = Pair(1, 2) ; std::cout << P.x << ' ' << P.y << std::endl ; } It seems to me that D should either not permit argument names to shadow the member names, since it has no initializer lists and all members are automatically initialized. Comments? -- Shriramana Sharma ஶ்ரீரமணஶர்மா श्रीरमणशर्मा
Re: Why do some language-defined attributes have @ and some not?
On Thursday, 23 October 2014 at 00:59:26 UTC, Shriramana Sharma via Digitalmars-d-learn wrote: I thought D was beyond carrying historical baggage. DMD 2.x is not necessarily language-compatible with DMD 2.(x+1) since the language is still evolving. You can deprecate one syntax and enforce the other in a later version. I submit that the syntax for attributes should be streamlined. Shall I go and open a Bugzilla item? LOL. I understand the sentiment, but it's a waste of time. We've long since reached the point where we try and not break people's existing code unless we have a really good reason for it (and for better or worse, aesthetics definitely don't make the cut). No, D2 is not as fixed in stone as C++ is, but we are trying to have a stable enough language for programmers to use in production rather than treating the language as being experimental and/or rapidly changing in incompatible ways. So, yes, we do have historical baggage, albeit nowhere near as much as C++ does. But the reality of the matter is that _every_ language that gets used in production has historical baggage, because you never get everything right, and you frequently can't afford to change it, because it would break too many existing programs. And for better or worse, fixing attribute names doesn't even come close to being on the list of things that Walter Bright would consider worth changing. It's hard enough to get him to agree to make breaking changes when most of us agree that we'll be better off with the changes in spite of the code breakage that they cause, let alone on a controversial topic like attribute names which has been discussed to death. Walter and Andrei very much want D to be being used in production at this point, and so the focus on features is entirely on what's required to make the language fully usuable for companies looking to use D, and tweaking things to make them cleaner just isn't going to happen without a really good, practical reason for it. Breaking changes are sometimes made still, but not for something like that - Jonathan M Davis
Re: Why do some language-defined attributes have @ and some not?
I thought D was beyond carrying historical baggage. DMD 2.x is not necessarily language-compatible with DMD 2.(x+1) since the language is still evolving. You can deprecate one syntax and enforce the other in a later version. I submit that the syntax for attributes should be streamlined. Shall I go and open a Bugzilla item? -- Shriramana Sharma ஶ்ரீரமணஶர்மா श्रीरमणशर्मा
Re: Destructor order
On 10/22/2014 04:05 PM, eles wrote: > And the compiler swallows this without even barking? The compiler must obey an alias this inside Scoped. I've thinking for a way do disallow this but haven't been able to spend much time on it today. > Why Scoped!A is convertible to A, then? So that Scoped!A can conveniently be used as an A. > And what the resulting A-typed variable contains if the object > gets destroyed. Note that the A is not the object but the class reference to it. The 'alias this' hands out a reference to the object that is on the stack. The reference is valid when that occurs. Then, the compiler destroys the temporary Scoped!A object as it should, leaving behind a dangling reference. There must be a way to disallow this. Ali
Re: Destructor order
On Wednesday, 22 October 2014 at 18:03:44 UTC, anonymous wrote: On Wednesday, 22 October 2014 at 15:45:02 UTC, eles wrote: D version: `foo` should be a `Scoped!A`. When it's typed as `A`, the `Scoped!A` that is returned by `scoped`, is destructed immediately (and the reference leaks, I guess). And the compiler swallows this without even barking? Why Scoped!A is convertible to A, then? And what the resulting A-typed variable contains if the object gets destroyed. And what use for that content?
Re: Destructor order
On Wednesday, 22 October 2014 at 18:03:44 UTC, anonymous wrote: On Wednesday, 22 October 2014 at 15:45:02 UTC, eles wrote: `foo` should be a `Scoped!A`. When it's typed as `A`, the `Scoped!A` that is returned by `scoped`, is destructed immediately (and the reference leaks, I guess). Just tell me that's a feature, not a bug...
Re: How the memory layout of global variable is reliable ?
On Wednesday, 22 October 2014 at 20:29:58 UTC, Cjkp wrote: Hello, I have an idea about a small code tool related to the application resources. It would rely on the assumption that some global variabled, sharing the same type and attributes, declared in group, are contiguous. In short I need to know if the following assertions are always true and reliable over time: -- import std.stdio; // used as base adress static string beg = ""; // arbitrary generated by a tool and mixed at compile time. static string a = ""; static string b = ""; static string c = ""; static string d = ""; static string e = ""; static string f = ""; void main(string args[]) { void* offs = &beg; assert( &a == (offs + (size_t.sizeof * 2) * 1) ); // length + ptr assert( &b == (offs + (size_t.sizeof * 2) * 2) ); // length + ptr assert( &c == (offs + (size_t.sizeof * 2) * 3) ); // etc. assert( &d == (offs + (size_t.sizeof * 2) * 4) ); } -- In a second time I need to be sure that the return tuple of the trait "allMembers" follow the declarations order. The documentation says that: "The order in which the strings appear in the result is not defined". But so far, it looks like it's ordered according to the declaration (at least for a module containing only some global variables). Any other remarks about the topic are welcome. Plese don't do this, it's undefined behavior and could make you code invalid with a new compiler release or different compiler. If possible use static arrays instead. int[2] arr=[1,2]; @property auto ref b(){ return arr[1]; } ---
How the memory layout of global variable is reliable ?
Hello, I have an idea about a small code tool related to the application resources. It would rely on the assumption that some global variabled, sharing the same type and attributes, declared in group, are contiguous. In short I need to know if the following assertions are always true and reliable over time: -- import std.stdio; // used as base adress static string beg = ""; // arbitrary generated by a tool and mixed at compile time. static string a = ""; static string b = ""; static string c = ""; static string d = ""; static string e = ""; static string f = ""; void main(string args[]) { void* offs = &beg; assert( &a == (offs + (size_t.sizeof * 2) * 1) ); // length + ptr assert( &b == (offs + (size_t.sizeof * 2) * 2) ); // length + ptr assert( &c == (offs + (size_t.sizeof * 2) * 3) ); // etc. assert( &d == (offs + (size_t.sizeof * 2) * 4) ); } -- In a second time I need to be sure that the return tuple of the trait "allMembers" follow the declarations order. The documentation says that: "The order in which the strings appear in the result is not defined". But so far, it looks like it's ordered according to the declaration (at least for a module containing only some global variables). Any other remarks about the topic are welcome.
Re: Using in as a parameter qualifier
On Wednesday, 22 October 2014 at 19:13:58 UTC, Shriramana Sharma via Digitalmars-d-learn wrote: Hello people. I'm once more looking at D since I participated here a bit last year. Since I'm still not 100% sure about committing myself to using D i.o. C++ for my work, I'd really like to resurrect this thread to clear my lingering doubts (the full thread is at http://forum.dlang.org/post/mailman.469.1369978600.13711.digitalmars-d-le...@puremagic.com if people need context): On 6/1/13, Jonathan M Davis wrote: The compiler will move an object rather than copy it when it can. So, for instance, if you pass the function a temporary, it'll move that temporary rather than copying it. However, if it's called with an lvalue, odds are that it's going to have to make a copy (though it might be moved if it were the last time in the caller that the variable was referenced). I read the Bartosz Milewski article that someone (Ali?) recommended once more. What I understood is that D avoids the copy-*constructor* when given an rvalue as a function parameter. But the article seems to indicate that D will still make a *blit* copy. However, Jonathan's comment above indicates otherwise (or am I misreading?). What is actually meant above by "move an object rather than copy"? In C++(11), move semantics seem to mostly involve a swap of pointers ponting to the data. Here we are talking about struct objects directly containing the data. Does "move" means that the content is going to be "moved" to a new location in memory i.e. copied and then the old memory freed? Moved means that the memory for the object is blitted from one location to another, so no copy is made and no destructors or constructors are run. There's never any freeing of memory involved, because it involves objects on the stack, not the heap. The memory that held the object will get reused at somepoint when the stack pointer moves to the appropriate point in the stack for that to make sense, but there's no allocation or deallocation going on regardless. What I'd really like to see D do (please tell me if it does that already) is to avoid constructing the struct twice, once at the caller site and second time at the callee site when I'm passing an rvalue struct as argument. For example: bezier.di: struct Bezier { int p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y ; } void draw(Bezier b) ; -- test.d: void main () { draw(Bezier(100, 100, 133, 200, 166, 200, 200, 200)) ; } should only ever cause the one Bezier struct object to be constructed because the rvalue is not used at the caller site. Does D do that already? That will result in a move operation. No copying will take place. And it technically, it may not actually move anything it all and just use the object where it's initially constructed. I'm not sure what the actual, generated machine code ends up doing in that regard. But there's no copying or double-construction. And even if what I'm passing to the draw function is an lvalue, say a Bezier b which I have declared in the previous line to draw under main(), if it is passed in with "in" keyword which implies "const", then the function is not going to change the value anyway, so there isn't any need to make a copy and so it makes sense if D actually directly uses the content of the variable declared under main(). Does D do this already too? const does _not_ mean that a copy doesn't need to be made. It has zero effect on that. In fact, if you're passing an lvaue to a function that doesn't take its arguments by ref, it's almost a guarantee that a copy will be made. The only exception would be if the compiler determines that the lvalue in question is never used after that call, in which case, it might just move the object rather than copy it. A further thought: If instead of draw(Bezier), I have Bezier.draw(), then the values will be taken from the Bezier object directly whether it is an lvalue or rvalue at the calling site, right? So, you mean if draw was a member function of Bezier, and you did something like Bezier(100, 100, 133, 200, 166, 200, 200, 200).draw() you want to know whether a copy of the Bezier object would be made? The this member of a struct is a ref - in this case ref Bezier - so it doesn't make a copy. The object would be constructed in place and then be destroyed after it's used (though exactly when it would be destroyed if the object were created and called in a complex expression, I'm not sure - possibly as soon as the function call terminated, possibly when the statement completed). And extending this, given that UFCS exists in D, draw(Bezier) and Bezier.draw() should be equivalent, meaning that if Bezier.draw() doesn't make a copy (even a blit) then draw(Bezier) shouldn't [assuming of course that it doesn't alter the contents of the object], right? If draw is a free function, then Bezier(100, 100, 133, 200, 166, 200, 200, 200).draw() is literally transformed
Re: Why do some language-defined attributes have @ and some not?
On Wednesday, 22 October 2014 at 19:13:58 UTC, Shriramana Sharma via Digitalmars-d-learn wrote: Hello. See http://dlang.org/attribute. 3 attributes starting at http://dlang.org/attribute#disable have a @ in front. Apparently safe, trusted and system also do, though these are documented elsewhere: http://dlang.org/function.html#function-safety. Why are some language-defined attributes starting with @ and others not? Wouldn't it be consistent and less-confusing to, say, only use @ for user-defined attributes and not these language-defined ones? It's a historical thing. Walter didn't want to add more keywords, so we put @ in the front of some of the new ones. User-defined attributes didn't even exist at the time. Those were added far later. It would be nice if none of the built-in attributes had @ on them, but it's far too late now. And by the way, there's also @property, so there's four of them with @. - Jonathan M Davis
Re: Removing whitespace duplicates
On Wednesday, 22 October 2014 at 19:00:36 UTC, Nordlöw wrote: On Tuesday, 21 October 2014 at 08:04:13 UTC, bearophile wrote: If your text is ASCII, then there is std.ascii.whitespace that can be given as argument to std.string.tr. Bye, bearophile http://dlang.org/phobos/std_ascii.html#.whitespace is of string but std.string.tr needs [string] as argument. How does that work? string a = "test \t \t test"; writeln(a.tr(std.ascii.whitespace,"_","s"));
Re: Using in as a parameter qualifier
Hello people. I'm once more looking at D since I participated here a bit last year. Since I'm still not 100% sure about committing myself to using D i.o. C++ for my work, I'd really like to resurrect this thread to clear my lingering doubts (the full thread is at http://forum.dlang.org/post/mailman.469.1369978600.13711.digitalmars-d-le...@puremagic.com if people need context): On 6/1/13, Jonathan M Davis wrote: > The compiler will move an object rather than copy it when it can. So, for > instance, if you pass the function a temporary, it'll move that temporary > rather than copying it. However, if it's called with an lvalue, odds are > that > it's going to have to make a copy (though it might be moved if it were the > last time in the caller that the variable was referenced). I read the Bartosz Milewski article that someone (Ali?) recommended once more. What I understood is that D avoids the copy-*constructor* when given an rvalue as a function parameter. But the article seems to indicate that D will still make a *blit* copy. However, Jonathan's comment above indicates otherwise (or am I misreading?). What is actually meant above by "move an object rather than copy"? In C++(11), move semantics seem to mostly involve a swap of pointers ponting to the data. Here we are talking about struct objects directly containing the data. Does "move" means that the content is going to be "moved" to a new location in memory i.e. copied and then the old memory freed? What I'd really like to see D do (please tell me if it does that already) is to avoid constructing the struct twice, once at the caller site and second time at the callee site when I'm passing an rvalue struct as argument. For example: bezier.di: struct Bezier { int p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y ; } void draw(Bezier b) ; -- test.d: void main () { draw(Bezier(100, 100, 133, 200, 166, 200, 200, 200)) ; } should only ever cause the one Bezier struct object to be constructed because the rvalue is not used at the caller site. Does D do that already? And even if what I'm passing to the draw function is an lvalue, say a Bezier b which I have declared in the previous line to draw under main(), if it is passed in with "in" keyword which implies "const", then the function is not going to change the value anyway, so there isn't any need to make a copy and so it makes sense if D actually directly uses the content of the variable declared under main(). Does D do this already too? A further thought: If instead of draw(Bezier), I have Bezier.draw(), then the values will be taken from the Bezier object directly whether it is an lvalue or rvalue at the calling site, right? And extending this, given that UFCS exists in D, draw(Bezier) and Bezier.draw() should be equivalent, meaning that if Bezier.draw() doesn't make a copy (even a blit) then draw(Bezier) shouldn't [assuming of course that it doesn't alter the contents of the object], right? Sorry if some of my statements above sound presumptuous, but I'm really really excited about D, and really really want to get away from C++, so please bear with me... Thanks! -- Shriramana Sharma ஶ்ரீரமணஶர்மா श्रीरमणशर्मा
Why do some language-defined attributes have @ and some not?
Hello. See http://dlang.org/attribute. 3 attributes starting at http://dlang.org/attribute#disable have a @ in front. Apparently safe, trusted and system also do, though these are documented elsewhere: http://dlang.org/function.html#function-safety. Why are some language-defined attributes starting with @ and others not? Wouldn't it be consistent and less-confusing to, say, only use @ for user-defined attributes and not these language-defined ones? -- Shriramana Sharma ஶ்ரீரமணஶர்மா श्रीरमणशर्मा
Re: Removing whitespace duplicates
On Tuesday, 21 October 2014 at 08:04:13 UTC, bearophile wrote: If your text is ASCII, then there is std.ascii.whitespace that can be given as argument to std.string.tr. Bye, bearophile http://dlang.org/phobos/std_ascii.html#.whitespace is of string but std.string.tr needs [string] as argument. How does that work?
Re: Destructor order
On Wed, 22 Oct 2014 18:44:26 + via Digitalmars-d-learn wrote: > On Wednesday, 22 October 2014 at 18:14:54 UTC, ketmar via > Digitalmars-d-learn wrote: > > yes, this is the case. i believe that this should be explicitly > > documented in `scoped` ddocs. documentation examples using > > 'auto', but there is no mention that this is what *must* be > > used. > This is too dangerous to be used in real programs… there is nothing really dangerous if the feature is used properly. i'm using `scoped` in my software without any troubles. yes, there might be better ways to do what `scoped` does, but for now `scoped` is... satisfactory. it just need some care. ;-) signature.asc Description: PGP signature
Re: Destructor order
On Wednesday, 22 October 2014 at 18:14:54 UTC, ketmar via Digitalmars-d-learn wrote: yes, this is the case. i believe that this should be explicitly documented in `scoped` ddocs. documentation examples using 'auto', but there is no mention that this is what *must* be used. This is too dangerous to be used in real programs…
Re: Sorting array of string arrays by an element in the string array
Neal: Interesting! Thank you. Memory isn't a problem Unfortunately currently the sort-decorate-undercorate in Phobos is not very fast. but I would still like to learn how to write more efficient programs. If i posted my code would you be able to give me some advice? There is far more than just me around here. If you post code, someone usually can write come comment. Bye, bearophile
Re: Destructor order
On Wed, 22 Oct 2014 18:03:44 + anonymous via Digitalmars-d-learn wrote: > On Wednesday, 22 October 2014 at 15:45:02 UTC, eles wrote: > > D version: > > > > { //displays ~A~B~C > > A foo = scoped!(A)(); > > B bar = scoped!(B)(); > > C caz = new C(); > > destroy(caz); > > } > > > > Why the objects are not destroyed in the inverse order of their > > creation? Case in point, destroying foo releases a lock for bar > > and caz. > > `foo` should be a `Scoped!A`. When it's typed as `A`, the > `Scoped!A` that is returned by `scoped`, is destructed > immediately (and the reference leaks, I guess). yes, this is the case. i believe that this should be explicitly documented in `scoped` ddocs. documentation examples using 'auto', but there is no mention that this is what *must* be used. signature.asc Description: PGP signature
Re: Destructor order
On 10/22/2014 08:45 AM, eles wrote:> C++ versions: > > { //displays ~C~B~A > A foo; > B bar; > C *caz = new C(); > delete caz; > } > > std::cout << std::endl; > > { //displays ~C~B~A > std::unique_ptr foo = std::make_unique(); > std::unique_ptr bar = std::make_unique(); > C *caz = new C(); > delete caz; > } > > > D version: > > { //displays ~A~B~C > A foo = scoped!(A)(); > B bar = scoped!(B)(); > C caz = new C(); > destroy(caz); > } > > Why the objects are not destroyed in the inverse order of their > creation? Case in point, destroying foo releases a lock for bar and caz. I confirm this. If you put writeln() expressions inside typecons.scoped, you will realize that the destroys are happening right after each scoped line: constructed A destroying ~A constructed B destroying ~B ~C Extremely dangerous and very tricky! The solution? Define the objects as 'auto' (or 'const', etc.), which you want anyway: auto foo = scoped!(A)(); auto bar = scoped!(B)(); You do not want to be left with A or B. You want Scoped!A and Scoped!B. Ali
Re: Destructor order
On Wednesday, 22 October 2014 at 15:45:02 UTC, eles wrote: D version: { //displays ~A~B~C A foo = scoped!(A)(); B bar = scoped!(B)(); C caz = new C(); destroy(caz); } Why the objects are not destroyed in the inverse order of their creation? Case in point, destroying foo releases a lock for bar and caz. `foo` should be a `Scoped!A`. When it's typed as `A`, the `Scoped!A` that is returned by `scoped`, is destructed immediately (and the reference leaks, I guess). Compare: import std.stdio; import std.typecons; class A {~this() {writeln("~A");}} class B {~this() {writeln("~B");}} class C {~this() {writeln("~C");}} void main() { { writeln("bad:"); A foo = scoped!(A)(); writeln("1"); B bar = scoped!(B)(); writeln("2"); } { writeln("good:"); auto foo = scoped!(A)(); writeln("1"); auto bar = scoped!(B)(); writeln("2"); } } prints: bad: ~A 1 ~B 2 good: 1 2 ~B ~A
Re: Sorting array of string arrays by an element in the string array
On Wednesday, 22 October 2014 at 07:38:01 UTC, bearophile wrote: neal: data.sort!q{ to!int(a[4]) > to!int(b[4]) }; This code fixes my problem! Thanks for the quick responses guys. you rock! That converts string->int many more than once for each string. So if memory is not a problem, consider using a decorate-sort-undecorate pattern: data.schwartzSort!q{ a[4].to!int }; Bye, bearophile Interesting! Thank you. Memory isn't a problem but I would still like to learn how to write more efficient programs. If i posted my code would you be able to give me some advice?
Re: Destructor order
On Wednesday, 22 October 2014 at 17:13:35 UTC, Ola Fosheim Grøstad wrote: On Wednesday, 22 October 2014 at 16:55:41 UTC, Regan Heath So why wasn't the eles' destructor order in reverse if Scoped is a struct and calls explicit destroy(B) then destroy(A)? Maybe it's the writeln() inside the destructor which behaves badly, albeit the same should have happened for structs too.
Re: Destructor order
On Wednesday, 22 October 2014 at 16:55:41 UTC, Regan Heath wrote: "The garbage collector is not guaranteed to run the destructor for all unreferenced objects. Furthermore, the order in which the garbage collector calls destructors for unreference objects is not specified. This means that when the garbage collector calls a destructor for an object of a class that has members that are references to garbage collected objects, those references may no longer be valid. This means that destructors cannot reference sub objects. This rule does not apply to auto objects or objects deleted with the DeleteExpression, as the destructor is not being run by the garbage collector, meaning all references are valid." But Scoped!A is on the stack? So why wasn't the eles' destructor order in reverse if Scoped is a struct and calls explicit destroy(B) then destroy(A)? https://github.com/D-Programming-Language/phobos/blob/master/std/typecons.d#L4628 ~this() { .destroy(Scoped_payload); }
Re: Destructor order
On Wed, 22 Oct 2014 16:49:20 +0100, eles wrote: On Wednesday, 22 October 2014 at 15:45:02 UTC, eles wrote: D version with structs: { //display ~C~B~A A foo; B bar; C *caz = new C(); delete caz; } as expected. Structs are special, compare: http://dlang.org/struct.html#struct-destructor with: http://dlang.org/class.html#destructors Specifically: "The garbage collector is not guaranteed to run the destructor for all unreferenced objects. Furthermore, the order in which the garbage collector calls destructors for unreference objects is not specified. This means that when the garbage collector calls a destructor for an object of a class that has members that are references to garbage collected objects, those references may no longer be valid. This means that destructors cannot reference sub objects. This rule does not apply to auto objects or objects deleted with the DeleteExpression, as the destructor is not being run by the garbage collector, meaning all references are valid." Regan -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Re: Destructor order
On Wednesday, 22 October 2014 at 15:45:02 UTC, eles wrote: D version with structs: { //display ~C~B~A A foo; B bar; C *caz = new C(); delete caz; } as expected.
Destructor order
C++ versions: { //displays ~C~B~A A foo; B bar; C *caz = new C(); delete caz; } std::cout << std::endl; { //displays ~C~B~A std::unique_ptr foo = std::make_unique(); std::unique_ptr bar = std::make_unique(); C *caz = new C(); delete caz; } D version: { //displays ~A~B~C A foo = scoped!(A)(); B bar = scoped!(B)(); C caz = new C(); destroy(caz); } Why the objects are not destroyed in the inverse order of their creation? Case in point, destroying foo releases a lock for bar and caz.
Re: Issue with WIKI example Win32_DLLs_in_D
I think there is a bigger issue with the mentioned example. The command cannot work: dmd test mydll.lib -g test.d has an import statement to mydll. mydll has to be included in the command. But as mydll not only contains the exported dll functions but also DllMain, it cannot be compiled together with test which contains the main entry point. Maybe the example can be corrected. Kind regards André On Tuesday, 21 October 2014 at 21:57:06 UTC, Laeeth Isharc wrote: Funnily enough I was just playing with this last night trying to get Excel to talk to dlang DLL. I borrowed a C example elsewhere on web and used a different .def file. Something like this: LIBRARY dprop DESCRIPTION 'My DLL written in D' EXETYPE NT CODEPRELOAD DISCARDABLE DATAWRITE EXPORTS useArray = useArray usemyTest = usemyTest Where the two functions exported from D to excel were as above. Try that and let me know. If that doesn't work I will send you a link to from repository.
Re: Beginner ?. Why does D suggest to learn java
On Wed, 22 Oct 2014 07:58:49 + Kagamin via Digitalmars-d-learn wrote: > That's quite inadequate criticism. If you don't know, what > features generics have, you can't criticize them. i'm don't saying that "generics are bad", i'm saying that D has alot more anyway with it's CTFE magic. and generics aren't metaprogramming tool. but my memory can be weak, so feel free to correct me. signature.asc Description: PGP signature
Re: Beginner ?. Why does D suggest to learn java
On Tuesday, 21 October 2014 at 12:19:43 UTC, ketmar via Digitalmars-d-learn wrote: templates arent about FP only. yet i agree that Scheme is a very good starting point, SICP rocks. It is available for free online: http://mitpress.mit.edu/sicp/ Scheme is good for teaching because it is a minimalistic language, so you quickly learn the semantic model which is more hidden in Haskell. But I really enjoyed this one: http://tryhaskell.org/ D should have a similar intro when the current quirks have been ironed out.
Re: Beginner ?. Why does D suggest to learn java
On Thursday, 16 October 2014 at 22:26:51 UTC, RBfromME wrote: I'm a newbie to programming and have been looking into the D lang as a general purposing language to learn, yet the D overview indicates that java would be a better language to learn for your first programming language. Why? Looks like D is easier than Java... D is far more complex programming language than Java. I do D programming for over decade, and Java for ~9 years (before I was a C++ programmmer). Just take a look at number of types you have in D, storage classes, pointers, modules (that will soon come to Java too), etc... D generics are superior to Java. However, Java generics are superasy. Java is designed to be an easy programming language, D is designed to be pragmatic. If people new to programming were about to start with D as the first language, I suggest them to start with an easy subset of it, and I humbly believe that subset will look very, very similar to Java. PS. this is not Java advocacy here, I am just trying to be fair and realistic. I just love D but if I said D is as easy as Java, that would be a lie.
Re: Beginner ?. Why does D suggest to learn java
On Tuesday, 21 October 2014 at 21:58:09 UTC, ketmar via Digitalmars-d-learn wrote: start from using templates as generics, then add some sugar, some type consitions, some CTFE and so on. with C# we will stop right after "generics", 'cause there is no other things there. That's quite inadequate criticism. If you don't know, what features generics have, you can't criticize them.
Re: Making plugin system with shared libraries. Upcast in shared lib
It's how COM casts objects http://msdn.microsoft.com/en-us/library/ms687230.aspx
Re: Making plugin system with shared libraries. Upcast in shared lib
The idea is that the object you work with is responsible for casting itself to an interface you need.
Re: How would you dive into a big codebase
On Wednesday, 22 October 2014 at 02:42:38 UTC, safety0ff wrote: On Wednesday, 22 October 2014 at 01:21:19 UTC, Freddy wrote: Is there any advice/tips for reading medium/big D codebases? Somewhat D specific: I would consider an IDE/editor like Eclipse with DDT that can give an outline of the data structures & functions names in a source file to make the files easier to digest. This would be my approach as well. The code navigation options offered by modern IDEs are way better than the alternatives, specially the semantic navigation "what gets used where". -- Paulo
Re: Sorting array of string arrays by an element in the string array
neal: data.sort!q{ to!int(a[4]) > to!int(b[4]) }; This code fixes my problem! Thanks for the quick responses guys. you rock! That converts string->int many more than once for each string. So if memory is not a problem, consider using a decorate-sort-undecorate pattern: data.schwartzSort!q{ a[4].to!int }; Bye, bearophile
Re: How would you dive into a big codebase
On Wednesday, 22 October 2014 at 02:09:53 UTC, Jonathan M Davis wrote: The usual suggestion that I've heard given (without any particular language in mind) is to start by tracking down and fixing a bug in it This is how I usually do it too, though you don't even need to find a bug in it. Picking any feature and trying to find it in the codebase and understand how it is implemented will usually serve well as an entry point. To understand all of the code, I'd start taking notes though, as they're useful to fall back on later. Either way, I wouldn't try to swallow all of it before starting to work with the code. I've been working on codebases just fine without understanding them in their entirety, as such is the magic of code separation. I'm pretty sure there are real codebases in the wild where nobody understands all of it. X11 comes to mind.