Re: DDoc with cross-references
On 2012-04-02 07:52, Ary Manzana wrote: On 4/2/12 12:39 PM, Jonathan M Davis wrote: Phobos' macros are in https://github.com/D-Programming-Language/d-programming- language.org/blob/master/std.ddoc As for linking macros, LREF is used for references within a module. XREF is used for references to std modules. CXREF is used for references to core modules. ECXREF is used for references to etc.c modules. Again, the same things. D has ddoc and it tries to do everything with ddoc. No, that's plain wrong. Links to other module members should be done automatically. And the links should come from the compiler. The compiler has that knowledge already, why loose it and work on a less powerful level (ddoc)? In general I think the compiler should automatically output cross-references. But there are cases when you want to manually refer to other parts of the documentation and in these cases you would needed these macros. -- /Jacob Carlborg
Re: DDoc with cross-references
On 2012-04-02 06:20, Ary Manzana wrote: I'm planning to add cross-references to the default ddoc output. At least that's the simplest thing I could do right now that might improve ddoc somehow. That would be so nice to have. -- /Jacob Carlborg
Re: Getting only the data members of a type
On 2012-04-02 02:43, Ary Manzana wrote: This is what I don't like about D. It gives you a hammer and everyone tries to solve all problems with that single hammer. Then you get duplicated code for basic stuff, like getting the type of a field, in many projects. It's a waste of time for a developer to have to sit down and think how we can cheat the compiler or make it talk to give us something it already knows, but only having a hammer to do so. Either put that in the language, or in the core library. But don't make people waste time. I'd suggest sending pull request with methods that accomplish those annoyances. On the other hand, take a look at the implementation of std.traits. Is it really a win to implement functionLinkage in D? Right here: https://github.com/D-Programming-Language/phobos/blob/master/std/traits.d#L704 you are repeating the linkages with their names, when that information is already available to the compiler. What's the point in duplicating information? The compiler already knows it, and much better than D. It could be implemented in a much simpler way. Is it just the pride of saying "Look what I can do with my powerful compile time reflection capabilities (basically stringof in that module)?" I'm not angry, but I don't think things are taking the correct direction... I agree. -- /Jacob Carlborg
Re: DDoc with cross-references
On 4/2/12 2:16 PM, Ary Manzana wrote: On 4/2/12 2:07 PM, Jonathan M Davis wrote: On Monday, April 02, 2012 13:52:47 Ary Manzana wrote: On 4/2/12 12:39 PM, Jonathan M Davis wrote: On Monday, April 02, 2012 12:20:31 Ary Manzana wrote: I'm planning to add cross-references to the default ddoc output. At least that's the simplest thing I could do right now that might improve ddoc somehow. I see the documentation generated for phobos, for example: http://dlang.org/phobos/std_array.html#Appender has anchors to the many symbols (in fact, now I notice it's flawed, because they are not fully-qualified). Does anyone know where can I get the macros for generating such output? I will need it for generating the cross-links. But a more appropriate question is: why the default ddoc output doesn't generate such anchors by default? At least putting an ID to the generated DT... Phobos' macros are in https://github.com/D-Programming-Language/d-programming- language.org/blob/master/std.ddoc As for linking macros, LREF is used for references within a module. XREF is used for references to std modules. CXREF is used for references to core modules. ECXREF is used for references to etc.c modules. Again, the same things. D has ddoc and it tries to do everything with ddoc. No, that's plain wrong. Links to other module members should be done automatically. And the links should come from the compiler. The compiler has that knowledge already, why loose it and work on a less powerful level (ddoc)? I'm not arguing it one way or another. I'm just pointing out how it works now. As for Appender, I don't see any links at all, so I don't know what you're talking about. The generic D macro (which just designates D code) is used by it in some places, and ddoc does put some stuff in italics in some cases (e.g. the name of a function's parameter in the documentation for that function), but there are no links in Appender's documentation. What I meant is, every member in the module has an anchor. In the case of Appender it looks like this in the generated HTML: That's why I can give you this link: http://dlang.org/phobos/std_array.html#Appender and it scrolls down to Appender (I know you know it already, but it seems I wasn't clear in my previous post). Now, that is flawed because the name is not fully qualified. And there's no macro to get a fully qualified name or link to other members modules. The anchors have been a big problem for a long time. A prime example of where they're horrible is std.datetime. They maintain _no_ hierarchy whatsoever. So, _everything_ gets lumped together as it were a free function, and if anything has the same name (e.g. DateTime and SysTime both have a year property), then they end up with identical anchors. The result is that the links at the top of std.datetime are nearly useless. It's ddoc's biggest problem IMHO. Thanks again. This is what I want to fix. I see this in the source code: DDOC_DECL = $(DT $(BIG $0))\n\ So what I want to do is to change that so that it includes an anchor. Should I change it to: DDOC_DECL = $(DT $(BIG $1))\n\ or something like that, and then pass two arguments? I find it hard to change the documentation output while having to deal with all those macros... Nevermind, found how to do it. I hope I can make it soon, hehe... :-P
Re: "ref const" parameters in functions
On Monday, 2 April 2012 at 05:03:48 UTC, Jonathan M Davis wrote: On Sunday, April 01, 2012 21:23:50 Jonathan M Davis wrote: On Monday, April 02, 2012 05:46:24 L-MAN wrote: Sure, if you have large structs, making a lot of copies of them can be expensive. But to avoid that, you're going to have to avoid coding in a way which creates temporaries, and expressions like (abc1+abc2*20.0)+(abc1*abc2+abc1*20.0) will _always_ create temporaries. The classic, arithmetic operators are classic examples of functions which create temporaries (all of which are rvalues). So, you can't code that way and expect to avoid temporaries. I should point out that with optimizations turned on, in some cases the compiler can optimize out the copying of temporaries, though not generally the temporaries themselves. For instance auto a = abc1 + abc2 * 20.0 results in a temporary for the result of * and a temporary for the result of +. But the temporary for the result of + will be optimized out (probably even without turning on optimizations), because you're using that result to initialize a variable. And while the result of * will result in a temporary, the copy that gets made when it's passed to opBinary!"+" should be optimized out when compiled with optimizations turned on. So, the optimizer should be able to reduce the problem a fair bit if you compile with -O. -inline may be able to reduce it even further. So, with optimizations turned on, you may not get anywhere near as many copies as you expected. And using auto ref for the parameters (which is easy with the overloaded arithmetic operators, since they're already templated) should also help reduce the number of copies made, but it _is_ up to the compiler whether it makes a copy or not with auto ref, so that depends on the compiler. So, you should be able to reduce the number of copies simply by compiling with -O and -inline, but the temporaries themselves will exist regardless. - Jonathan M Davis Thank you)) it's very good for me))
Re: Add Element to list not Working
Thanks. I tried doing this and the list didn't update: void AddToList( SList!int list, int i ) { list.insert( i ); } SList!int intList; AddToList( intList, 42 ); but when I switched to this, it worked: SList!int intList; void AddToList( int i ) { intList.insert( i ); } AddToList( 42 ); The first method didn't give an error it just didn't update the list as I thought. Any idea? On Monday, 2 April 2012 at 06:07:40 UTC, Ali Çehreli wrote: On 04/01/2012 10:45 PM, Chris Pons wrote: I'm trying to add an element to a list with insert but that doesn't seem to do anything at all. If I try using ~= it says that "Error: cannot append type Node to type SList!(Node). I'm pretty confused about using ~= because it works fine for arrays but apperantly not for lists. How do I add an element to a list? import std.stdio; import std.container; void main() { auto l = SList!int(); l.insert(42);// inserts front l.insert(43);// this too assert(l == SList!int(43, 42)); // inserts after the specified range (l[] is the entire list) l.insertAfter(l[], 44); assert(l == SList!int(43, 42, 44)); // This doesn't work because SList.Range doesn't define opOpAssign!"~" // l[] ~= 45; } Ali
Re: DDoc with cross-references
On 4/2/12 2:07 PM, Jonathan M Davis wrote: On Monday, April 02, 2012 13:52:47 Ary Manzana wrote: On 4/2/12 12:39 PM, Jonathan M Davis wrote: On Monday, April 02, 2012 12:20:31 Ary Manzana wrote: I'm planning to add cross-references to the default ddoc output. At least that's the simplest thing I could do right now that might improve ddoc somehow. I see the documentation generated for phobos, for example: http://dlang.org/phobos/std_array.html#Appender has anchors to the many symbols (in fact, now I notice it's flawed, because they are not fully-qualified). Does anyone know where can I get the macros for generating such output? I will need it for generating the cross-links. But a more appropriate question is: why the default ddoc output doesn't generate such anchors by default? At least putting an ID to the generated DT... Phobos' macros are in https://github.com/D-Programming-Language/d-programming- language.org/blob/master/std.ddoc As for linking macros, LREF is used for references within a module. XREF is used for references to std modules. CXREF is used for references to core modules. ECXREF is used for references to etc.c modules. Again, the same things. D has ddoc and it tries to do everything with ddoc. No, that's plain wrong. Links to other module members should be done automatically. And the links should come from the compiler. The compiler has that knowledge already, why loose it and work on a less powerful level (ddoc)? I'm not arguing it one way or another. I'm just pointing out how it works now. As for Appender, I don't see any links at all, so I don't know what you're talking about. The generic D macro (which just designates D code) is used by it in some places, and ddoc does put some stuff in italics in some cases (e.g. the name of a function's parameter in the documentation for that function), but there are no links in Appender's documentation. What I meant is, every member in the module has an anchor. In the case of Appender it looks like this in the generated HTML: That's why I can give you this link: http://dlang.org/phobos/std_array.html#Appender and it scrolls down to Appender (I know you know it already, but it seems I wasn't clear in my previous post). Now, that is flawed because the name is not fully qualified. And there's no macro to get a fully qualified name or link to other members modules. The anchors have been a big problem for a long time. A prime example of where they're horrible is std.datetime. They maintain _no_ hierarchy whatsoever. So, _everything_ gets lumped together as it were a free function, and if anything has the same name (e.g. DateTime and SysTime both have a year property), then they end up with identical anchors. The result is that the links at the top of std.datetime are nearly useless. It's ddoc's biggest problem IMHO. Thanks again. This is what I want to fix. I see this in the source code: DDOC_DECL = $(DT $(BIG $0))\n\ So what I want to do is to change that so that it includes an anchor. Should I change it to: DDOC_DECL = $(DT $(BIG $1))\n\ or something like that, and then pass two arguments? I find it hard to change the documentation output while having to deal with all those macros...
Re: Add Element to list not Working
On 2 April 2012 17:45, Chris Pons wrote: > I'm trying to add an element to a list with insert but that doesn't seem to > do anything at all. If I try using ~= it says that "Error: cannot append > type Node to type SList!(Node). I'm pretty confused about using ~= because > it works fine for arrays but apperantly not for lists. > > How do I add an element to a list? opAppend (or whatever it is) isn't defined for alot of types that it probably should be. There should be an append method that you can use though. -- James Miller
Re: Add Element to list not Working
On 04/01/2012 10:45 PM, Chris Pons wrote: I'm trying to add an element to a list with insert but that doesn't seem to do anything at all. If I try using ~= it says that "Error: cannot append type Node to type SList!(Node). I'm pretty confused about using ~= because it works fine for arrays but apperantly not for lists. How do I add an element to a list? import std.stdio; import std.container; void main() { auto l = SList!int(); l.insert(42);// inserts front l.insert(43);// this too assert(l == SList!int(43, 42)); // inserts after the specified range (l[] is the entire list) l.insertAfter(l[], 44); assert(l == SList!int(43, 42, 44)); // This doesn't work because SList.Range doesn't define opOpAssign!"~" // l[] ~= 45; } Ali
Re: DDoc with cross-references
On Monday, April 02, 2012 13:52:47 Ary Manzana wrote: > On 4/2/12 12:39 PM, Jonathan M Davis wrote: > > On Monday, April 02, 2012 12:20:31 Ary Manzana wrote: > >> I'm planning to add cross-references to the default ddoc output. At > >> least that's the simplest thing I could do right now that might improve > >> ddoc somehow. > >> > >> I see the documentation generated for phobos, for example: > >> > >> http://dlang.org/phobos/std_array.html#Appender > >> > >> has anchors to the many symbols (in fact, now I notice it's flawed, > >> because they are not fully-qualified). > >> > >> Does anyone know where can I get the macros for generating such output? > >> I will need it for generating the cross-links. > >> > >> But a more appropriate question is: why the default ddoc output doesn't > >> generate such anchors by default? At least putting an ID to the > >> generated DT... > > > > Phobos' macros are in > > > > https://github.com/D-Programming-Language/d-programming- > > language.org/blob/master/std.ddoc > > > > As for linking macros, > > > > LREF is used for references within a module. > > XREF is used for references to std modules. > > CXREF is used for references to core modules. > > ECXREF is used for references to etc.c modules. > > Again, the same things. D has ddoc and it tries to do everything with > ddoc. No, that's plain wrong. Links to other module members should be > done automatically. And the links should come from the compiler. The > compiler has that knowledge already, why loose it and work on a less > powerful level (ddoc)? I'm not arguing it one way or another. I'm just pointing out how it works now. > > As for Appender, I don't see any links at all, so I don't know what you're > > talking about. The generic D macro (which just designates D code) is used > > by it in some places, and ddoc does put some stuff in italics in some > > cases (e.g. the name of a function's parameter in the documentation for > > that function), but there are no links in Appender's documentation. > > What I meant is, every member in the module has an anchor. In the case > of Appender it looks like this in the generated HTML: > > > > That's why I can give you this link: > > http://dlang.org/phobos/std_array.html#Appender > > and it scrolls down to Appender (I know you know it already, but it > seems I wasn't clear in my previous post). > > Now, that is flawed because the name is not fully qualified. And there's > no macro to get a fully qualified name or link to other members modules. The anchors have been a big problem for a long time. A prime example of where they're horrible is std.datetime. They maintain _no_ hierarchy whatsoever. So, _everything_ gets lumped together as it were a free function, and if anything has the same name (e.g. DateTime and SysTime both have a year property), then they end up with identical anchors. The result is that the links at the top of std.datetime are nearly useless. It's ddoc's biggest problem IMHO. - Jonathan M Davis
Re: DDoc with cross-references
On 4/2/12 12:39 PM, Jonathan M Davis wrote: On Monday, April 02, 2012 12:20:31 Ary Manzana wrote: I'm planning to add cross-references to the default ddoc output. At least that's the simplest thing I could do right now that might improve ddoc somehow. I see the documentation generated for phobos, for example: http://dlang.org/phobos/std_array.html#Appender has anchors to the many symbols (in fact, now I notice it's flawed, because they are not fully-qualified). Does anyone know where can I get the macros for generating such output? I will need it for generating the cross-links. But a more appropriate question is: why the default ddoc output doesn't generate such anchors by default? At least putting an ID to the generated DT... Phobos' macros are in https://github.com/D-Programming-Language/d-programming- language.org/blob/master/std.ddoc As for linking macros, LREF is used for references within a module. XREF is used for references to std modules. CXREF is used for references to core modules. ECXREF is used for references to etc.c modules. Again, the same things. D has ddoc and it tries to do everything with ddoc. No, that's plain wrong. Links to other module members should be done automatically. And the links should come from the compiler. The compiler has that knowledge already, why loose it and work on a less powerful level (ddoc)? As for Appender, I don't see any links at all, so I don't know what you're talking about. The generic D macro (which just designates D code) is used by it in some places, and ddoc does put some stuff in italics in some cases (e.g. the name of a function's parameter in the documentation for that function), but there are no links in Appender's documentation. What I meant is, every member in the module has an anchor. In the case of Appender it looks like this in the generated HTML: That's why I can give you this link: http://dlang.org/phobos/std_array.html#Appender and it scrolls down to Appender (I know you know it already, but it seems I wasn't clear in my previous post). Now, that is flawed because the name is not fully qualified. And there's no macro to get a fully qualified name or link to other members modules.
Add Element to list not Working
I'm trying to add an element to a list with insert but that doesn't seem to do anything at all. If I try using ~= it says that "Error: cannot append type Node to type SList!(Node). I'm pretty confused about using ~= because it works fine for arrays but apperantly not for lists. How do I add an element to a list?
Re: std.typecons.Ref(T).opImplicitCastTo()
On Monday, April 02, 2012 07:23:23 Alex Rønne Petersen wrote: > On 02-04-2012 06:25, Jonathan M Davis wrote: > > alias this is not supposed to be restricted such that you can only have > > one > > per type. That's a temporary, implementation problem. TDPL specifically > > talks about having multiple alias thises per type. > > > > - Jonathan M Davis > > What is the reason it hasn't been realized yet? I don't know. While we're getting closer to having everything in TDPL implemented correctly each release, there's still plenty of stuff left to do, and no one has tackled the alias this issue yet. I expect that it's not an entirely easy thing to fix and that other stuff has been higher priority. http://d.puremagic.com/issues/show_bug.cgi?id=6083 The major thing being tackled this release has been const-correctness, and it's not done yet (in spite of there now being a beta for 2.059). I believe that that's been one of Walter's major focuses this release cycle, and I wouldn't really expect him to tackle anything else major until Object's const- correctness been sorted out. Nothing is stopping someone else from doing it, but no one has. Plenty of other stuff has been fixed though. - Jonathan M Davis
Re: std.typecons.Ref(T).opImplicitCastTo()
On 02-04-2012 06:25, Jonathan M Davis wrote: On Monday, April 02, 2012 05:41:00 Alex Rønne Petersen wrote: On 30-03-2012 19:28, Jonathan M Davis wrote: On Friday, March 30, 2012 16:27:44 simendsjo wrote: Is opImplicitCastTo a planned feature? It's only used in this type as I can see, and it doesn't add implicit casting. It's been discussed, but I don't think that it's ever been agreed upon. In theory, alias this is meant to deal with implicit casts. I don't know whay anything in Phobos would have such a function. And I don't know what the point of std.typecons.Ref really is. It's undocumented (and clearly is _intended_ to be undocumented given what the comment is started with). I suspect that it's an old idea that just hasn't been cleaned out. If you'll notice, it also has opDot, which is being removed from the language. - Jonathan M Davis But you can only have one alias this per type. It is outright incompatible with the idea of implicit cast operators. It's like restricting opCast to only one overload per function - a not-very-pragmatic decision if you ask me... alias this is not supposed to be restricted such that you can only have one per type. That's a temporary, implementation problem. TDPL specifically talks about having multiple alias thises per type. - Jonathan M Davis What is the reason it hasn't been realized yet? -- - Alex
Re: "ref const" parameters in functions
On Sunday, April 01, 2012 21:23:50 Jonathan M Davis wrote: > On Monday, April 02, 2012 05:46:24 L-MAN wrote: > Sure, if you have large structs, making a lot of copies of them can be > expensive. But to avoid that, you're going to have to avoid coding in a way > which creates temporaries, and expressions like > > (abc1+abc2*20.0)+(abc1*abc2+abc1*20.0) > > will _always_ create temporaries. The classic, arithmetic operators are > classic examples of functions which create temporaries (all of which are > rvalues). So, you can't code that way and expect to avoid temporaries. I should point out that with optimizations turned on, in some cases the compiler can optimize out the copying of temporaries, though not generally the temporaries themselves. For instance auto a = abc1 + abc2 * 20.0 results in a temporary for the result of * and a temporary for the result of +. But the temporary for the result of + will be optimized out (probably even without turning on optimizations), because you're using that result to initialize a variable. And while the result of * will result in a temporary, the copy that gets made when it's passed to opBinary!"+" should be optimized out when compiled with optimizations turned on. So, the optimizer should be able to reduce the problem a fair bit if you compile with -O. -inline may be able to reduce it even further. So, with optimizations turned on, you may not get anywhere near as many copies as you expected. And using auto ref for the parameters (which is easy with the overloaded arithmetic operators, since they're already templated) should also help reduce the number of copies made, but it _is_ up to the compiler whether it makes a copy or not with auto ref, so that depends on the compiler. So, you should be able to reduce the number of copies simply by compiling with -O and -inline, but the temporaries themselves will exist regardless. - Jonathan M Davis
Re: DDoc with cross-references
On Monday, April 02, 2012 12:20:31 Ary Manzana wrote: > I'm planning to add cross-references to the default ddoc output. At > least that's the simplest thing I could do right now that might improve > ddoc somehow. > > I see the documentation generated for phobos, for example: > > http://dlang.org/phobos/std_array.html#Appender > > has anchors to the many symbols (in fact, now I notice it's flawed, > because they are not fully-qualified). > > Does anyone know where can I get the macros for generating such output? > I will need it for generating the cross-links. > > But a more appropriate question is: why the default ddoc output doesn't > generate such anchors by default? At least putting an ID to the > generated DT... Phobos' macros are in https://github.com/D-Programming-Language/d-programming- language.org/blob/master/std.ddoc As for linking macros, LREF is used for references within a module. XREF is used for references to std modules. CXREF is used for references to core modules. ECXREF is used for references to etc.c modules. As for Appender, I don't see any links at all, so I don't know what you're talking about. The generic D macro (which just designates D code) is used by it in some places, and ddoc does put some stuff in italics in some cases (e.g. the name of a function's parameter in the documentation for that function), but there are no links in Appender's documentation. - Jonathan M Davis
Re: std.typecons.Ref(T).opImplicitCastTo()
On Monday, April 02, 2012 15:36:01 James Miller wrote: > On 31 March 2012 06:28, Jonathan M Davis wrote: > > it also has > > opDot, which is being removed from the language. > > Out of curiosity, what was opDot? An overload of the dot operator. So, if you had A a = foo(); a.func(); and A implemented opDot, instead of A's func being called, the overloaded opDot would be called. I don't know exactly how it was implemented. It's either a D1-only thing or an early D2 thing, but I've never used it, and it's not supposed to be in the language anymore (though like a number of other features that are supposed to be gone, it may not have actually have been deprecated yet). It's probably similar to how -> is overloadable in C++, which can then be useful for stuff like smart pointer types so that they can forward function calls to the object pointed to by the smart pointer. - Jonathan M Davis
Re: DDoc with cross-references
On 4/2/12 12:20 PM, Ary Manzana wrote: I'm planning to add cross-references to the default ddoc output. At least that's the simplest thing I could do right now that might improve ddoc somehow. I see the documentation generated for phobos, for example: http://dlang.org/phobos/std_array.html#Appender has anchors to the many symbols (in fact, now I notice it's flawed, because they are not fully-qualified). Does anyone know where can I get the macros for generating such output? I will need it for generating the cross-links. But a more appropriate question is: why the default ddoc output doesn't generate such anchors by default? At least putting an ID to the generated DT... I also wonder why it's not implemented. I mean, it seems *so* easy to do it. Just add a toDdocChars() method to every Dsymbol. For basic types, just output their string representation (int, float, etc.). For classes, structs, etc, just output: struct_name or something like that...
Re: std.typecons.Ref(T).opImplicitCastTo()
On Monday, April 02, 2012 05:41:00 Alex Rønne Petersen wrote: > On 30-03-2012 19:28, Jonathan M Davis wrote: > > On Friday, March 30, 2012 16:27:44 simendsjo wrote: > >> Is opImplicitCastTo a planned feature? > >> It's only used in this type as I can see, and it doesn't add implicit > >> casting. > > > > It's been discussed, but I don't think that it's ever been agreed upon. In > > theory, alias this is meant to deal with implicit casts. I don't know whay > > anything in Phobos would have such a function. And I don't know what the > > point of std.typecons.Ref really is. It's undocumented (and clearly is > > _intended_ to be undocumented given what the comment is started with). I > > suspect that it's an old idea that just hasn't been cleaned out. If > > you'll notice, it also has opDot, which is being removed from the > > language. > > > > - Jonathan M Davis > > But you can only have one alias this per type. It is outright > incompatible with the idea of implicit cast operators. It's like > restricting opCast to only one overload per function - a > not-very-pragmatic decision if you ask me... alias this is not supposed to be restricted such that you can only have one per type. That's a temporary, implementation problem. TDPL specifically talks about having multiple alias thises per type. - Jonathan M Davis
DDoc with cross-references
I'm planning to add cross-references to the default ddoc output. At least that's the simplest thing I could do right now that might improve ddoc somehow. I see the documentation generated for phobos, for example: http://dlang.org/phobos/std_array.html#Appender has anchors to the many symbols (in fact, now I notice it's flawed, because they are not fully-qualified). Does anyone know where can I get the macros for generating such output? I will need it for generating the cross-links. But a more appropriate question is: why the default ddoc output doesn't generate such anchors by default? At least putting an ID to the generated DT...
Re: "ref const" parameters in functions
On Monday, April 02, 2012 05:46:24 L-MAN wrote: > About temporaries in operators +-/*.. you're right, it is not a > secret. > references in other functions (not in operators) too. > > > I can't understand one thing: > ABC abc; // ABC is a struct that consists of some 4x4 matrix for > example > ABC abc2 = ABC(20); > ABC abc3 = ABC(..); > . > abc+=abc2+abc3; > > operation "+" return the copy of it result to the internal > temporary stack variable $temp (it creates automatically and it > disable to use and invisible to see), but > $temp is a variable and > it must be an lvalue always. No. It's not. It's a temporary, and temporaries are almost always rvalues. The sole (and very bizarre) exception is struct literals (e.g. ABC(20) is currently considered an lvalue). It results in the bizarre situation that a function which takes a const ref will work with ABC(20) but won't work with a function that returns ABC(20). It's a point of debate and may be changed, in which case ABC(20) would not be an lvalue anymore. But regardless, the result of operations such as + are _always_ rvalues. Normally, the only items that are lvalues are variables and return values which are ref. The result of a function or operator such as + is most definitely _not_ an lvalue, since you can't return their results by ref. It's a classic example on an rvalue. If you want to avoid making copies, then you're going to need to make your parameters auto ref (and hope that the compiler decides that making a copy is more expensive - I don't know how it decides that) or make them const ref and use lvalues - and using lvalues generally means creating explicit variables and _not_ using temporaries. So, your long expression with + and * would have to be changed to use += and *=. > when I draw to the screen 5 graphical objects by OpenGL, it > uses a matrices operation via D-language structures (uses all > math operators and makes some matrices operations for every > graphical object on the scene for each time), the unnecessary > copyes of it(matrices) is very bad for engine performance. Sure, if you have large structs, making a lot of copies of them can be expensive. But to avoid that, you're going to have to avoid coding in a way which creates temporaries, and expressions like (abc1+abc2*20.0)+(abc1*abc2+abc1*20.0) will _always_ create temporaries. The classic, arithmetic operators are classic examples of functions which create temporaries (all of which are rvalues). So, you can't code that way and expect to avoid temporaries. - Jonathan M Davis
Re: "ref const" parameters in functions
On Sunday, 1 April 2012 at 08:22:08 UTC, Jonathan M Davis wrote: On Sunday, April 01, 2012 09:10:58 L-MAN wrote: On Saturday, 31 March 2012 at 21:42:05 UTC, Jonathan M Davis wrote: > On Saturday, March 31, 2012 23:25:51 L-MAN wrote: >> Hello everybody! >> >> I'm trying to use some function FN like this: >> >> struct X >> { >> >> protected double _x; // double type for example >> public @property double X() const { return _x; } >> >> // ctor >> public this(double x) { _x = x; } // double type for >> example >> >> void FN(ref const(double) in_x) // double type for example >> { >> >> // ... do some operations with _x >> >> } >> >> } >> >> main(..) >> { >> >> >> X x = X(20); >> >> x.FN(30); // getting an error >> >> } >> >> why x.FN(20) gets me an error? >> the construction "ref const(double)" or "ref >> >> immutable(double)" >> must be an rvalue by default I think, but in FN parameter >> the >> compiler expects an lvalue... >> >> this strategy is the way to some unnecessary copy >> operations, >> >> when value 20 (or some big struct instead of it) will copy >> to >> the >> stack.. >> >> How can I resolve this problem? > > Unlike C++, const ref _must_ be an lvalue just like ref. If > you > use auto ref > instead of const ref, the compiler is supposed to choose > between ref and non- > ref based on which it thinks would be more efficient, but it > currently only > works with templated types. > > You can duplicate the function and have a version whose > parameter is const ref > and one which is not, but be careful if you try and make the > non-const ref > version call the const ref version (to avoid duplicating the > function's body) > and make sure that you don't get infinite recursion. It > usually > works, but I've > run into cases before where I ended up with infinite > recursion, > so make sure > that you have unit tests which check. > > Regardless, if you're dealing with a primitive type like > double, don't bother > with const ref. It's not going to be more efficient. It's > with > large structs > that you can see a difference. > > - Jonathan M Davis Thank you for reply, but how can I exclude some copy operations? Look at this sample: struct ABC // simple class { private double _d=0; @property { double D() const { return _d; } double D(double val) { return _d=val; } } this(double d) { _d = d; writeln(" *** ctor ABC, d = ", _d); } ABC opAdd(ABC abc) { //ABC temp = ABC(this._d+abc._d); //return temp; return ABC(this._d+abc._d); } ABC opMul(double d) { //ABC temp = ABC(this._d*d); //return temp; return ABC(this._d*d); } ref ABC opAssign(ABC abc) { this._d = abc.D; return this; } ~this() { writeln(" *** dtor ABC, d = ", _d); } } struct F { private ABC _abc; @property double D() const { return _abc.D; } public this(ABC abc) { _abc = abc; //abc.D=90; //pnt.X = 30; } } void main(string[] args) { ABC abc1 = ABC(10); ABC abc2 = ABC(20); F f = F(abc1+abc2*20.0); writeln(f.D); ... } Operation abc1+abc2*20.0 consists of 2 ABC copy: 1. Copy result of abc2*20.0 temp value to opAdd function 2. Copy result of abc1+abc2*20.0 temp2 value to F() ctor two temp variables and two copy operations. But if I can use "ref const" rvalue operations 0 copies will be need: abc2*20.0 creates temp valiable $$$temp opAdd(ref const ABC abc) use a ref rvalue to $$$temp, is not a copy opAdd return a $$$temp2 that use as ref rvalue for F() ctor And try to imagine how many unnecessary copies of ABC will create a simple operation like this: ((abc1+abc2*20.0)/0.25) + (abc1/abc2)*(abc2-1) it killing a time of application, especially if time is critical. The constructions "auto ref" in return functions values are not working well, if I use it in a "auto ref opAdd(ref const ABC)" "auto ref opMul(double d)" " F.this(ref const ABC)" to exclude some copy operations it gives me a strange result :-(( You misunderstood what I meant by auto ref. I meant that you use auto ref instead of const ref. e.g. void func(auto ref T param) {} At present, func would have to be templated to use auto ref void func(T)(auto ref T param) {} but eventually, auto ref shouldn't need the function to be templated. Returning auto ref is completely different. It says that the return type is inferred (just like with returning auto by itself) except that it's a reference to the type which is inferred. And that requires that the value being returned by an lvalue which is _not_ a local var
Re: std.typecons.Ref(T).opImplicitCastTo()
On 30-03-2012 19:28, Jonathan M Davis wrote: On Friday, March 30, 2012 16:27:44 simendsjo wrote: Is opImplicitCastTo a planned feature? It's only used in this type as I can see, and it doesn't add implicit casting. It's been discussed, but I don't think that it's ever been agreed upon. In theory, alias this is meant to deal with implicit casts. I don't know whay anything in Phobos would have such a function. And I don't know what the point of std.typecons.Ref really is. It's undocumented (and clearly is _intended_ to be undocumented given what the comment is started with). I suspect that it's an old idea that just hasn't been cleaned out. If you'll notice, it also has opDot, which is being removed from the language. - Jonathan M Davis But you can only have one alias this per type. It is outright incompatible with the idea of implicit cast operators. It's like restricting opCast to only one overload per function - a not-very-pragmatic decision if you ask me... -- - Alex
Re: std.typecons.Ref(T).opImplicitCastTo()
On 31 March 2012 06:28, Jonathan M Davis wrote: > it also has > opDot, which is being removed from the language. Out of curiosity, what was opDot? -- James Miller
Re: Getting only the data members of a type
On 4/1/12 8:09 PM, Jacob Carlborg wrote: On 2012-04-01 08:18, Ali Çehreli wrote: On 03/31/2012 09:09 PM, Artur Skawina wrote: > > enum s = cast(S*)null; > foreach (i, m; s.tupleof) { > enum name = S.tupleof[i].stringof[4..$]; > alias typeof(m) type; > writef("(%s) %s\n", type.stringof, name); > } > > Real Programmers don't use std.traits. ;) > > artur Your method works but needing to iterate on a struct variable by s.tupleof and having to use the struct type as S.tupleof in the loop body is strange. Yeah, it's a bit strange. One could think that it would be possible to use "m.stringof" but that just returns the type. Instead of using "s.tupleof" it's possible to use "typeof(S.tupleof)". Have a look at: https://github.com/jacob-carlborg/orange/blob/master/orange/util/Reflection.d#L212 It's possible to get the type of a field as well, based on the name: https://github.com/jacob-carlborg/orange/blob/master/orange/util/Reflection.d#L237 This is what I don't like about D. It gives you a hammer and everyone tries to solve all problems with that single hammer. Then you get duplicated code for basic stuff, like getting the type of a field, in many projects. It's a waste of time for a developer to have to sit down and think how we can cheat the compiler or make it talk to give us something it already knows, but only having a hammer to do so. Either put that in the language, or in the core library. But don't make people waste time. I'd suggest sending pull request with methods that accomplish those annoyances. On the other hand, take a look at the implementation of std.traits. Is it really a win to implement functionLinkage in D? Right here: https://github.com/D-Programming-Language/phobos/blob/master/std/traits.d#L704 you are repeating the linkages with their names, when that information is already available to the compiler. What's the point in duplicating information? The compiler already knows it, and much better than D. It could be implemented in a much simpler way. Is it just the pride of saying "Look what I can do with my powerful compile time reflection capabilities (basically stringof in that module)?" I'm not angry, but I don't think things are taking the correct direction...
Re: UFCS for types?
On 31 March 2012 21:37, simendsjo wrote: > Is is possible to use UFCS for types to simulate static members? > > struct S { > static void f(); > } > > void ext(S)() { > S.f(); > } > > void main() { > ext!S(); // ok > S.ext(); // Error: no property 'ext' for type 'S' > } As far as I know UFCS just rewrites `a.f(b,c)` to `f(a,b,c)`, so probably not, since `S.ext()` would be re-written to `ext(S)`, which obviously makes no sense. Its pretty much just syntatic sugar with a few disambiguation rules. Basically you're asking for UFCS for template parameters, but that would introduce too many ambiguities, especially considering things like alias parameters: ext(alias T, U)(U a); int foo = 1; foo.ext() //does the alias T get the value, or the U a? If you just remember that UFCS is just for functions, not templates, or rather its Uniform Function-Call Syntax, not Uniform Template-Instantiation Syntax (UTIS?). Because even ext(T)(); is just sugar for: template ext(T) { void ext(); } -- James Miller
Re: std.json dynamic initialization of JSONValue
Nicolas Silva wrote: On Sat, Mar 31, 2012 at 12:25 PM, Piotr Szturmaj wrote: I have written streaming json parser using ranges. It returns slices when possible. Benchmarked it and it's about 2.05x the speed of std.json. It gives possibility to "dig" into the structure and stream (using ranges) by member fields, array elements, or characters of field names and string values. It's possible to parse JSON without a single allocation. For convenience, one can get objects, arrays and strings as a whole. I plan to add a streaming json writer and release it (currently it outputs json using toString()). I've seen questions on stackoverflow about parsing 500 MB JSON... so streaming feature makes it really universal. This approach should be good for XML parser too. Currently, I don't have time to improve it. But if someone is interested I can send it as is :-) I'm very interested in your json lib. I just started writing my own but you have more advanced stuff already so I'd better build something on top of your work. Is it on a repository somewhere on the web? I just uploaded it here: https://github.com/pszturmaj/json-streaming-parser. Hope you like it :-)
Re: Whats the best way to get a struct/class member type?
On Sat, 31 Mar 2012 15:20:42 +0200, simendsjo wrote: Seems __traits doesn't have a __traits(getMemberType, T, name). Now I'm doing the following: T t; // instance to use in getMember alias typeof( __traits(getMember, t, name) ) MemberType; Is this the only way to get the type of a field based on the name? I'd think so, apart from tupleof, as Jacob's already mentioned. It's easily factored out, though: template getMemberType(T, string name) if (is(typeof(__traits(getMember, T, name { alias typeof(__traits(getMember, T, name)) getMemberType; }
Re: Where does "U" in Rebindable.Rebindable come from?
On Fri, 30 Mar 2012 19:52:50 +0200, simendsjo wrote: On Fri, 30 Mar 2012 17:13:25 +0200, Simen Kjærås wrote: Indeed. The thing is - U is basically *set* by the isExpression. It says 'yes, there is such a U, so I'll add it to the local scope.'. This means that U will be set for the entire scope within which the static if exists. Due to the way the criteria are phrased, U is defined when the criteria are not met, and as such are defined in the else clause instead of the if clause. { // Outer scope starts here. static if ( !is( const(int) t == const(U), U ) ) { // isExpression returned false, so U is undefined } else { // But here it is defined, because we're still in the same, // broader scope. } } // And here it's no longer defined. Was that any better? I admit I didn't understand it at first either, but then I remembered that static if does not introduce a new scope. That helped. I knew static if didn't create a new scope, but I still thought U would not be defined if it didn't match, but it seems it is defined just by existing in the scope. I had a bug when I tried to reproduce the behavior: I used typeof(U), which is, of course, not possible as U is a type :) Thanks for the explanation. Allowed to use D at work yet btw? Not really. I use it a lot for scripts and fast prototyping, but it's not the most flexible of organizations. Could use it for internal tools, likely.
Re: Nested interface
Thanks; entered as issue 7807. On Sunday, 1 April 2012 at 20:17:09 UTC, Timon Gehr wrote: On 04/01/2012 08:13 PM, Read Bixby wrote: Hm, I guess it's much simpler than that. I must not be understanding something about covariance. The following code produces the same error message (it has nothing to do with nestedness or shared classes): interface Interface { Interface getNext(); const(Interface) getNext() const; } class Implementation : Interface { Implementation getNext() { return null; } const(Implementation) getNext() const { return null; } } This is a compiler bug. It works if 'Interface' is changed to an abstract class. Please report this issue to the bug tracker: http://d.puremagic.com/issues/
Re: Nested interface
On 04/01/2012 08:13 PM, Read Bixby wrote: Hm, I guess it's much simpler than that. I must not be understanding something about covariance. The following code produces the same error message (it has nothing to do with nestedness or shared classes): interface Interface { Interface getNext(); const(Interface) getNext() const; } class Implementation : Interface { Implementation getNext() { return null; } const(Implementation) getNext() const { return null; } } This is a compiler bug. It works if 'Interface' is changed to an abstract class. Please report this issue to the bug tracker: http://d.puremagic.com/issues/
Re: Read a unicode character from the terminal
On 2012-04-01 16:02, Ali Çehreli wrote: No difference in that example because it consumes the entire input as dchars. But in general, with that inefficient range, it is possible to pull just one dchar from the input and leave the rest of the stream untouched. For example, it would be possible to readf() an int right after that: auto u = byUnicode(); dchar d = u.front; // <-- reads just one dchar from the range int i; readf("%s", &i); // <-- continues with std.stdio functions writeln(i); With the getline() method, the int must be looked up in the line first, then from the input. Ali Ok, I see, thanks. -- /Jacob Carlborg
Re: Nested interface
Hm, I guess it's much simpler than that. I must not be understanding something about covariance. The following code produces the same error message (it has nothing to do with nestedness or shared classes): interface Interface { Interface getNext(); const(Interface) getNext() const; } class Implementation : Interface { Implementation getNext() { return null; } const(Implementation) getNext() const { return null; } } On Sunday, 1 April 2012 at 16:40:55 UTC, Read Bixby wrote: I was working on a small personal project, and ran across something I think might (or might not) be a bug. I'm posting in this particular group just in case it's a restriction somewhere that I just don't know about, or maybe just the way that covariance gets resolved. The obvious workaround is to return NestedInterface from the two methods of the derived class rather than NestedImplementation, but I was kind of surprised it didn't compile (in the actual code, both the nested interface and the nested implementation were called "Node" which was stupid on my part). I got the error message: "Error: class Implementation.NestedImplementation ambiguous virtual function getNext" Is this something anyone is likely to care about? shared interface Interface { public static shared interface NestedInterface { public shared(NestedInterface) getNext(); public shared(const(NestedInterface)) getNext() const; } } shared class Implementation : Interface { public static shared class NestedImplementation : Interface.NestedInterface { public override shared(NestedImplementation) getNext() { return null; } public override shared(const(NestedImplementation)) getNext() const { return null; } } }
Nested interface
I was working on a small personal project, and ran across something I think might (or might not) be a bug. I'm posting in this particular group just in case it's a restriction somewhere that I just don't know about, or maybe just the way that covariance gets resolved. The obvious workaround is to return NestedInterface from the two methods of the derived class rather than NestedImplementation, but I was kind of surprised it didn't compile (in the actual code, both the nested interface and the nested implementation were called "Node" which was stupid on my part). I got the error message: "Error: class Implementation.NestedImplementation ambiguous virtual function getNext" Is this something anyone is likely to care about? shared interface Interface { public static shared interface NestedInterface { public shared(NestedInterface) getNext(); public shared(const(NestedInterface)) getNext() const; } } shared class Implementation : Interface { public static shared class NestedImplementation : Interface.NestedInterface { public override shared(NestedImplementation) getNext() { return null; } public override shared(const(NestedImplementation)) getNext() const { return null; } } }
Re: Simulating multiple inheritance
On 03/31/2012 10:05 AM, Andrej Mitrovic wrote: One issue with the new wxWidgets 2.9.x series is that there seem to be more multiply-inherited classes than before A bit more complete snippet. interface Foo { void doFoo(); } // Foo implementation mixin template FooMixin() { alias typeof(this) thisClass; void doFoo() { thisClass.init(); } } class Bar { void doFoo() {} } class Baz :Bar, Foo { alias Bar.doFoo BarFoo; mixin FooMixin; void init() {} } hth
Re: Read a unicode character from the terminal
On 04/01/2012 05:00 AM, Jacob Carlborg wrote: On 2012-04-01 01:17, Ali Çehreli wrote: On 03/31/2012 11:53 AM, Ali Çehreli wrote: > The solution is to use ranges when pulling Unicode characters out of > strings. std.stdin does not provide this yet, but it will eventually > happen (so I've heard :)). Here is a Unicode character range, which is unfortunately pretty inefficient because it relies on an exception that is thrown from isValidDchar! :p Ok, what's the differences compared to the example in your first post: void main() { string line = readln(); foreach (dchar c; line) { writeln(c); } } No difference in that example because it consumes the entire input as dchars. But in general, with that inefficient range, it is possible to pull just one dchar from the input and leave the rest of the stream untouched. For example, it would be possible to readf() an int right after that: auto u = byUnicode(); dchar d = u.front; // <-- reads just one dchar from the range int i; readf("%s", &i);// <-- continues with std.stdio functions writeln(i); With the getline() method, the int must be looked up in the line first, then from the input. Ali
Re: std.json dynamic initialization of JSONValue
On Sat, Mar 31, 2012 at 12:25 PM, Piotr Szturmaj wrote: > Andrej Mitrovic wrote: >> >> On 12/1/11, Kai Meyer wrote: >>> >>> I'm finding std.json extremely well written, with one glaring exception. >> >> >> I'm finding it to be crap. The last time I used it I just kept getting >> access violations (or was that std.xml? They're both crap when I used >> them.). ae.json beats its pants off for its simplicity + you get >> toJson/jsonParse for serialization and a way to skip serializing >> fields since a recent commit . It's easy to write your own >> tree-walking routines as well. >> >> But whatever works for people. :) > > > I have written streaming json parser using ranges. It returns slices when > possible. Benchmarked it and it's about 2.05x the speed of std.json. > > It gives possibility to "dig" into the structure and stream (using ranges) > by member fields, array elements, or characters of field names and string > values. It's possible to parse JSON without a single allocation. For > convenience, one can get objects, arrays and strings as a whole. > > I plan to add a streaming json writer and release it (currently it outputs > json using toString()). I've seen questions on stackoverflow about parsing > 500 MB JSON... so streaming feature makes it really universal. This approach > should be good for XML parser too. > > Currently, I don't have time to improve it. But if someone is interested I > can send it as is :-) I'm very interested in your json lib. I just started writing my own but you have more advanced stuff already so I'd better build something on top of your work. Is it on a repository somewhere on the web?
Re: Getting only the data members of a type
On 04/01/12 14:10, Jacob Carlborg wrote: > On 2012-04-01 11:27, Artur Skawina wrote: > >> That's because the compiler won't accept "foreach (i, t; S.tupleof)" and > > But it accepts "foreach (i, t; typeof(S.tupleof))". It does - thank you. This means that that ugly null-to-pointer cast from my example can go, and all that's needed is: foreach (i, type; typeof(S.tupleof)) { enum name = S.tupleof[i].stringof[4..$]; writef("(%s) %s\n", type.stringof, name); } artur
Re: Simulating multiple inheritance
On 03/31/2012 10:05 AM, Andrej Mitrovic wrote: This is related to wrapping wxWidgets. One issue with the new wxWidgets 2.9.x series is that there seem to be more multiply-inherited classes than before As Jacob already said mixin templates and Interfaces are the way to go. I think you have to define the mixin template as *mixin* template mixin_name. interface Baz {} mixin template Baz() { // In case that you need to access the parent class alias typeof(this) ThisClass; } class Bar {} class Foo : Bar , Baz { mixin Baz; } Good to know that you are still develop the wxWidget bindings. Keep us informed.
Re: Getting only the data members of a type
On 2012-04-01 11:27, Artur Skawina wrote: That's because the compiler won't accept "foreach (i, t; S.tupleof)" and "*.tupleof[i].stringof" is necessary to get the original name. This would have worked too: enum name = *s.tupleof[i].stringof[4..$]; but obfuscates the code more and looks like dereferencing a null pointer. artur But it accepts "foreach (i, t; typeof(S.tupleof))". -- /Jacob Carlborg
Re: Getting only the data members of a type
On 2012-04-01 08:18, Ali Çehreli wrote: On 03/31/2012 09:09 PM, Artur Skawina wrote: > > enum s = cast(S*)null; > foreach (i, m; s.tupleof) { > enum name = S.tupleof[i].stringof[4..$]; > alias typeof(m) type; > writef("(%s) %s\n", type.stringof, name); > } > > Real Programmers don't use std.traits. ;) > > artur Your method works but needing to iterate on a struct variable by s.tupleof and having to use the struct type as S.tupleof in the loop body is strange. Yeah, it's a bit strange. One could think that it would be possible to use "m.stringof" but that just returns the type. Instead of using "s.tupleof" it's possible to use "typeof(S.tupleof)". Have a look at: https://github.com/jacob-carlborg/orange/blob/master/orange/util/Reflection.d#L212 It's possible to get the type of a field as well, based on the name: https://github.com/jacob-carlborg/orange/blob/master/orange/util/Reflection.d#L237 -- /Jacob Carlborg
Re: Read a unicode character from the terminal
On 2012-04-01 00:14, Stewart Gordon wrote: On 31/03/2012 16:56, Jacob Carlborg wrote: How would I read a unicode character from the terminal? I've tried using "std.cstream.din.getc" but it seems to only work for ascii characters. If I try to read and print something that isn't ascii, it just prints a question mark. What OS are you using? And what codepage is the console set to? I'm using Mac OS X and the terminal is set to handle UTF-8. You might want to try the console module in my utility library: http://pr.stewartsplace.org.uk/d/sutil/ (For D1 at the moment, but a D2 version will be available any day now!) Stewart. I'll have a look, thanks. -- /Jacob Carlborg
Re: Read a unicode character from the terminal
On 2012-04-01 01:17, Ali Çehreli wrote: On 03/31/2012 11:53 AM, Ali Çehreli wrote: > The solution is to use ranges when pulling Unicode characters out of > strings. std.stdin does not provide this yet, but it will eventually > happen (so I've heard :)). Here is a Unicode character range, which is unfortunately pretty inefficient because it relies on an exception that is thrown from isValidDchar! :p Ok, what's the differences compared to the example in your first post: void main() { string line = readln(); foreach (dchar c; line) { writeln(c); } } -- /Jacob Carlborg
Re: Read a unicode character from the terminal
On 2012-03-31 20:53, Ali Çehreli wrote: I recommend using stdin. The destiny of std.cstream is uncertain and stdin is sufficient. (I know that it lacks support for BOM but I don't need them.) I thought std.cstream was a stream wrapper around stdin. The word 'character' used to mean characters of the Latin-based alphabets but with Unicode support that's not the case anymore. In D, 'character' means UTF code unit, nothing else. Unfortunately, although 'Unidode character' is just the correct term to use, it conflicts with D's characters which are not Unicode characters. 'Unicode code point' is the non-conflicting term that matches what we mean with 'Unicode character.' Only dchar can hold code points. That's the part about characters. Yeah, exactly. When I think about it, I don't know why I thought "getc" would work since it only returns a "char" and not a "dchar". The other side is what is being fed into the program through its standard input. On my Linux consoles, the text comes as a stream of chars, i.e. a UTF-8 encoded text. You must ensure that your terminal is capable of supporting Unicode through its settings. On Windows terminals, one must enter 'chcp 65001' to set the terminal to UTF-8. I'm on Mac OS X, the terminal is capable of handling Unicode. Then, it is the program that must know what the data represents. If you are expecting a Unicode code point, then you may think that is should be as simple as reading into a dchar: import std.stdio; void main() { dchar letter; readf("%s", &letter); // <-- does not work! writeln(letter); } The output: $ ./deneme ç Ã <-- will be different on different consoles I tried that as well. The problem is, char can implicitly be converted to dchar. Since the letter ç consists of two chars (two UTF-8 code units), dchar gets the first one converted as a dchar. To see this, read and write two chars in a loop without a newline in between: import std.stdio; void main() { foreach (i; 0 .. 2) { char code; readf("%s", &code); write(code); } writeln(); } This time two code units are read and then outputted to form a Unicode character on the console: $ ./deneme ç ç <-- result of two write(code) expressions The solution is to use ranges when pulling Unicode characters out of strings. std.stdin does not provide this yet, but it will eventually happen (so I've heard :)). For now, this is a way of getting Unicode characters from the input: import std.stdio; void main() { string line = readln(); foreach (dchar c; line) { writeln(c); } } Once you have the input as a string, std.utf.decode can also be used. Ali I'll give that a try, thanks. -- /Jacob Carlborg
Re: Simulating multiple inheritance
On 2012-03-31 19:05, Andrej Mitrovic wrote: This is related to wrapping wxWidgets. One issue with the new wxWidgets 2.9.x series is that there seem to be more multiply-inherited classes than before. In particular some of the main classes have become MI classes (e.g. wxApp derives from wxAppConsole which is now an MI class). Some wrappers (like wx.net) maintain these classes manually and simply discard MI altogether and make every class a singly-inherited class. SWIG does a similar thing too. E.g. in wx.net wxApp on the C# side looks like this: The first thing that pops up in my mind is using interfaces and template mixins, something like this: http://pastebin.com/jWMKQ6yy -- /Jacob Carlborg
Re: Problem with receiveOnly and classes
> Either way, I once tried to pass over "ownership" of trees of objects to > other threads but gave up on that. I don't think std.concurrency and D > really can work like that. (?) Concurrency seems to work much better > when you pass messages and data, structs are fine, and then build object > trees from that on the other side etc. Sorry I can't help more. I finally found a solution, thanks to your post: make a struct holding the object (and alias it so I can use it "nearly" transparently). I do not really like it, but it solves my problem. Would it be possible to integrate this into std.concurrency? I am newbie in D (my background is C++) Here is sample code: import std.stdio; import std.concurrency; class A{ public: void fun()const{ writeln("A.fun()");} } class B : A{ public: override void fun()const{ writeln("B.fun()");} } immutable struct P(T){ public: immutable(T) t; alias t this; this(immutable(T) _t)immutable{ t = _t; } } void producer(Tid t){ auto a = new immutable(A); auto b = new immutable(B); auto p1 = new P!A(a); auto p2 = new P!A(b); t.send(p1); t.send(p2); } void main(){ auto t = spawn(&producer, thisTid); while(1){ receive( (P!A* a){ writeln("matched P!A*"); a.fun(); }, (Variant v){ writeln("Unknown"); } ); } }
Re: Getting only the data members of a type
On 04/01/12 11:27, Artur Skawina wrote: > On 04/01/12 08:18, Ali Çehreli wrote: >> On 03/31/2012 09:09 PM, Artur Skawina wrote: >>> This will print all fields of struct/class S: >>> >>> enum s = cast(S*)null; >>> foreach (i, m; s.tupleof) { >>>enum name = S.tupleof[i].stringof[4..$]; >>>alias typeof(m) type; >>>writef("(%s) %s\n", type.stringof, name); >>> } >>> >>> Real Programmers don't use std.traits. ;) >>> >>> artur >> >> Your method works but needing to iterate on a struct variable by s.tupleof >> and having to use the struct type as S.tupleof in the loop body is strange. > > That's because the compiler won't accept "foreach (i, t; S.tupleof)" and > "*.tupleof[i].stringof" is necessary to get the original name. This would > have worked too: > > enum name = *s.tupleof[i].stringof[4..$]; > > but obfuscates the code more and looks like dereferencing a null pointer. That should have been: enum name = typeof(*s).tupleof[i].stringof[4..$]; artur
Re: Getting only the data members of a type
On 04/01/12 08:18, Ali Çehreli wrote: > On 03/31/2012 09:09 PM, Artur Skawina wrote: >> On 03/31/12 21:09, Ali Çehreli wrote: >>> How can I determine just the data members of a struct or class, excluding >>> the member functions? isCallable() comes short as member variable that have >>> opCall() defined are also callable: >> [...] >>> Wait! I found a solution before sending this message. :P isIntegral() works: >>> >>> if (isIntegral!(typeof(mixin("S." ~ member { >>> >>> Now the output is: >>> >>> i is a member function >>> m is a member variable<-- good but dubious >>>foo is a member variable >> [...] >> >> Don't forget about templates (appear as members too, but don't have a type). > > I see. We can't even use isCallable or isIntegral with a template member. > Assuming S has this member function template: > > void bar(T)() > {} > > Then we get the following error: > > /usr/include/d/dmd/phobos/std/traits.d(3223): Error: (S).bar(T) has no value > > I don't know a way of saying "if a template". eg: static if (!__traits(compiles, &__traits(getMember, obj, name))) or just static if (!is(typeof(member))) >> This will print all fields of struct/class S: >> >> enum s = cast(S*)null; >> foreach (i, m; s.tupleof) { >>enum name = S.tupleof[i].stringof[4..$]; >>alias typeof(m) type; >>writef("(%s) %s\n", type.stringof, name); >> } >> >> Real Programmers don't use std.traits. ;) >> >> artur > > Your method works but needing to iterate on a struct variable by s.tupleof > and having to use the struct type as S.tupleof in the loop body is strange. That's because the compiler won't accept "foreach (i, t; S.tupleof)" and "*.tupleof[i].stringof" is necessary to get the original name. This would have worked too: enum name = *s.tupleof[i].stringof[4..$]; but obfuscates the code more and looks like dereferencing a null pointer. artur
Re: "ref const" parameters in functions
On Sunday, April 01, 2012 09:10:58 L-MAN wrote: > On Saturday, 31 March 2012 at 21:42:05 UTC, Jonathan M Davis > > wrote: > > On Saturday, March 31, 2012 23:25:51 L-MAN wrote: > >> Hello everybody! > >> > >> I'm trying to use some function FN like this: > >> > >> struct X > >> { > >> > >> protected double _x; // double type for example > >> public @property double X() const { return _x; } > >> > >> // ctor > >> public this(double x) { _x = x; } // double type for example > >> > >> void FN(ref const(double) in_x) // double type for example > >> { > >> > >> // ... do some operations with _x > >> > >> } > >> > >> } > >> > >> main(..) > >> { > >> > >> > >> X x = X(20); > >> > >> x.FN(30); // getting an error > >> > >> } > >> > >> why x.FN(20) gets me an error? > >> the construction "ref const(double)" or "ref > >> > >> immutable(double)" > >> must be an rvalue by default I think, but in FN parameter the > >> compiler expects an lvalue... > >> > >> this strategy is the way to some unnecessary copy operations, > >> > >> when value 20 (or some big struct instead of it) will copy to > >> the > >> stack.. > >> > >> How can I resolve this problem? > > > > Unlike C++, const ref _must_ be an lvalue just like ref. If you > > use auto ref > > instead of const ref, the compiler is supposed to choose > > between ref and non- > > ref based on which it thinks would be more efficient, but it > > currently only > > works with templated types. > > > > You can duplicate the function and have a version whose > > parameter is const ref > > and one which is not, but be careful if you try and make the > > non-const ref > > version call the const ref version (to avoid duplicating the > > function's body) > > and make sure that you don't get infinite recursion. It usually > > works, but I've > > run into cases before where I ended up with infinite recursion, > > so make sure > > that you have unit tests which check. > > > > Regardless, if you're dealing with a primitive type like > > double, don't bother > > with const ref. It's not going to be more efficient. It's with > > large structs > > that you can see a difference. > > > > - Jonathan M Davis > > Thank you for reply, but how can I exclude some copy operations? > Look at this sample: > > struct ABC // simple class > { > private double _d=0; > @property > { > double D() const { return _d; } > double D(double val) { return _d=val; } > } > > this(double d) > { > _d = d; > writeln(" *** ctor ABC, d = ", _d); > } > > ABC opAdd(ABC abc) > { > //ABC temp = ABC(this._d+abc._d); > //return temp; > return ABC(this._d+abc._d); > } > > ABC opMul(double d) > { > //ABC temp = ABC(this._d*d); > //return temp; > return ABC(this._d*d); > } > > ref ABC opAssign(ABC abc) > { > this._d = abc.D; > return this; > } > > ~this() > { > writeln(" *** dtor ABC, d = ", _d); > } > } > > > struct F { > > private ABC _abc; > > @property double D() const { return _abc.D; } > > public this(ABC abc) > { > _abc = abc; > > //abc.D=90; > //pnt.X = 30; > } > } > > > void main(string[] args) > { >ABC abc1 = ABC(10); >ABC abc2 = ABC(20); >F f = F(abc1+abc2*20.0); >writeln(f.D); > ... > } > > Operation abc1+abc2*20.0 consists of 2 ABC copy: > 1. Copy result of abc2*20.0 temp value to opAdd function > 2. Copy result of abc1+abc2*20.0 temp2 value to F() ctor > two temp variables and two copy operations. > But if I can use "ref const" rvalue operations 0 copies will be > need: >abc2*20.0 creates temp valiable $$$temp >opAdd(ref const ABC abc) use a ref rvalue to $$$temp, is not a > copy >opAdd return a $$$temp2 that use as ref rvalue for F() ctor > And try to imagine how many unnecessary copies of ABC will create > a simple operation like this: > ((abc1+abc2*20.0)/0.25) + (abc1/abc2)*(abc2-1) >it killing a time of application, especially if time is > critical. > > The constructions "auto ref" in return functions values are not > working well, if I use it in a "auto ref opAdd(ref const ABC)" > "auto ref opMul(double d)" " F.this(ref const ABC)" to exclude > some copy operations it gives me a strange result :-(( You misunderstood what I meant by auto ref. I meant that you use auto ref instead of const ref. e.g. void func(auto ref T param) {} At present, func would have to be templated to use auto ref void func(T)(auto ref T param) {} but eventually, auto ref shouldn't need the function to be templated. Returning auto ref is completely different. It says that the return type is inferred (just like with returning auto by itself)
Re: "ref const" parameters in functions
On Saturday, 31 March 2012 at 21:42:05 UTC, Jonathan M Davis wrote: On Saturday, March 31, 2012 23:25:51 L-MAN wrote: Hello everybody! I'm trying to use some function FN like this: struct X { protected double _x; // double type for example public @property double X() const { return _x; } // ctor public this(double x) { _x = x; } // double type for example void FN(ref const(double) in_x) // double type for example { // ... do some operations with _x } } main(..) { X x = X(20); x.FN(30); // getting an error } why x.FN(20) gets me an error? the construction "ref const(double)" or "ref immutable(double)" must be an rvalue by default I think, but in FN parameter the compiler expects an lvalue... this strategy is the way to some unnecessary copy operations, when value 20 (or some big struct instead of it) will copy to the stack.. How can I resolve this problem? Unlike C++, const ref _must_ be an lvalue just like ref. If you use auto ref instead of const ref, the compiler is supposed to choose between ref and non- ref based on which it thinks would be more efficient, but it currently only works with templated types. You can duplicate the function and have a version whose parameter is const ref and one which is not, but be careful if you try and make the non-const ref version call the const ref version (to avoid duplicating the function's body) and make sure that you don't get infinite recursion. It usually works, but I've run into cases before where I ended up with infinite recursion, so make sure that you have unit tests which check. Regardless, if you're dealing with a primitive type like double, don't bother with const ref. It's not going to be more efficient. It's with large structs that you can see a difference. - Jonathan M Davis Thank you for reply, but how can I exclude some copy operations? Look at this sample: struct ABC // simple class { private double _d=0; @property { double D() const { return _d; } double D(double val) { return _d=val; } } this(double d) { _d = d; writeln(" *** ctor ABC, d = ", _d); } ABC opAdd(ABC abc) { //ABC temp = ABC(this._d+abc._d); //return temp; return ABC(this._d+abc._d); } ABC opMul(double d) { //ABC temp = ABC(this._d*d); //return temp; return ABC(this._d*d); } ref ABC opAssign(ABC abc) { this._d = abc.D; return this; } ~this() { writeln(" *** dtor ABC, d = ", _d); } } struct F { private ABC _abc; @property double D() const { return _abc.D; } public this(ABC abc) { _abc = abc; //abc.D=90; //pnt.X = 30; } } void main(string[] args) { ABC abc1 = ABC(10); ABC abc2 = ABC(20); F f = F(abc1+abc2*20.0); writeln(f.D); ... } Operation abc1+abc2*20.0 consists of 2 ABC copy: 1. Copy result of abc2*20.0 temp value to opAdd function 2. Copy result of abc1+abc2*20.0 temp2 value to F() ctor two temp variables and two copy operations. But if I can use "ref const" rvalue operations 0 copies will be need: abc2*20.0 creates temp valiable $$$temp opAdd(ref const ABC abc) use a ref rvalue to $$$temp, is not a copy opAdd return a $$$temp2 that use as ref rvalue for F() ctor And try to imagine how many unnecessary copies of ABC will create a simple operation like this: ((abc1+abc2*20.0)/0.25) + (abc1/abc2)*(abc2-1) it killing a time of application, especially if time is critical. The constructions "auto ref" in return functions values are not working well, if I use it in a "auto ref opAdd(ref const ABC)" "auto ref opMul(double d)" " F.this(ref const ABC)" to exclude some copy operations it gives me a strange result :-(( Thank you!!!