Re: copying const struct
On Monday, 14 October 2013 at 18:36:00 UTC, Maxim Fomin wrote: Funniest thing happen in cases like this when he reports the bug himself and soon fixes it, later bug is hit by someone else but during reporting it is realized that bug is already fixed, pull is pushed to master and everyone salutes Kenji. Obviously Kenji has a time machine. With it, he discovers bugs in the future and fixes them in the present and sometimes even in the past.
Re: howto dispatch to derived classes?
=?UTF-8?B?QWxpIMOHZWhyZWxp?= wrote: a virtual function like accept() can do the trick This would require changes in the whole class hierarchy. But because of The actual type of the object is implicitly stored in the vtbl of each type. and in addition, because the statement | writeln( getC.classinfo.create.classinfo); gives the correct type there should be a possibility to dispatch to the correct `visit' function without any changes in the class hierarchy. I see that a sequence of statements | if( auto tmp= cast(Ci) getC) visit( tmp); can dispatch to the correct `visit' function. But this again would require knowledge of all `Ci'. A solution seems very close, but ... -manfred
Is this a bug, if so, how would you summarize it?
See this code: http://dpaste.dzfl.pl/b3ae1667 On DMD it gives the error message if version=bug, but not if version=bug AND version=workaround1 (through 6). On LDC it segfaults at run time if version=bug, but not if version=bug AND version=workaround1 (through 6). Workaround1 - workaround4 are more or less boring. However it is surprising that workaround5 and workaround6 work but in the bug (when there's two aliases) you then get an error message for each alias.
Problem: Cannot create class out of nothing using witchcraft
dmd v2.063.2 Hi there! I'm terribly hopeful that you're more interested in the problem at hand than my choice of title. I've been using D for a while as my language of choice for various projects here and there, and I've recently discovered that template programming is magic. This is good. As part of the process of finding anything magic that also works, I've been going completely overboard with it. This involves, among other things, creating empty classes using templates and mixins at compile time, to build an inheritance hierarchy to do fancy things. This is all essentially irrelevant, but brings us to my issue. The next logical step in my adventure here was to see if I could create classes that weren't empty, but in fact has data members, generated at compile time using variadic templates. The first run-through went super well, and I was able to create classes with arbitrary primitive data types. However, ultimately I wanted these compile-time-generated classes with arbitrary data members to have data members that were of the type of the other classes that were also generated at compile time. That is to say, I want to generate, at compile time, classes like this: class MyClass { crazyTemplate!(MagicClassOne).MagicClassOne t1; crazyTemplate2!(MagicClassTwo).MagicClassTwo t2; } such that crazyTemplate and crazyTemplate2 each generate a class definition at compile time, accessible as defined by the string parameter. For example: template crazyTemplate(string classname) { mixin(`class ` ~ className ~ ` {}`); } The bare class-generating templates work, and generating classes that have arbitrary members at compile time using variadic templates given an arbitrary list of basic types works, but as soon as I try to use these template-generated classes as the types of the members of this variadic template, things go awry. I feel like what I'm trying to explain is a bit difficult to parse without a minimal working example, so here is one: code - import std.stdio; import std.typetuple; import std.traits; import std.conv; class BaseClass {} template ChildT(string className) { mixin(`class ` ~ className ~ ` : BaseClass {}`); } template isChildOrBaseClass(T) { enum bool isChildOrBaseClass = is(T : BaseClass); } template GrabBagT(string className, T...) if (allSatisfy!(isChildOrBaseClass, T)) { mixin(genClassStr!(T)(className)); } string genClassStr(T...)(string className) { string classStr = ; classStr ~= `static class ` ~ className ~ ` : BaseClass`; classStr ~= `{`; // Demonstrate that the template itself is not the problem classStr ~= `ChildT!(BestChild).BestChild t1000;`; // Add arbitrary data members foreach (i, TI; T) { // Neither of these work with the generated classes, but the first // will work if GrabBagT is called with primitive types and its // constraint is commented out //classStr ~= fullyQualifiedName!(TI) ~ ` t` ~ to!(string)(i) ~ `;`; //classStr ~= __traits(identifier, TI) ~ ` t` ~ to!(string)(i) ~ `;`; } classStr ~= `void printAttempts() {`; foreach (i, TI; T) { classStr ~= `writeln(` ~ to!string(i) ~ `);`; } classStr ~= `}`; classStr ~= `}`; return classStr; } int main(string[] args) { alias ChildT!(WorstChild).WorstChild WorstChild; alias ChildT!(MiddleChild).MiddleChild MiddleChild; auto magicObject = new GrabBagT!( MagicClass, WorstChild, MiddleChild).MagicClass(); //auto magicObject = new GrabBagT!( //MagicClass, int, float).MagicClass(); magicObject.printAttempts(); return 0; } - That should compile and print out 0 and 1. Note the template constraint that bars the template instantiator from trying to instantiate GrabBagT with anything other than types that can be implicitly treated as type BaseClass. I tried using __traits(identifier) and fullyQualifiedName to get the actual type of the alias passed in (like the BestChild declaration), but the latter gives a mangled name, and the former gives just whatever the bare alias was. In any case. If the fullyQualifiedName line is uncommented, the error is: classAttributeGen.d(22): Error: undefined identifier '__T6ChildTVAyaa10_576f7273744368696c64Z' classAttributeGen.d(22): Error: classAttributeGen.__T6ChildTVAyaa10_576f7273744368696c64Z.WorstChild is used as a type classAttributeGen.d(22): Error: undefined identifier '__T6ChildTVAyaa11_4d6964646c654368696c64Z' classAttributeGen.d(22): Error: classAttributeGen.__T6ChildTVAyaa11_4d6964646c654368696c64Z.MiddleChild is used as a type classAttributeGen.d(54): Error: template instance classAttributeGen.GrabBagT!(MagicClass, WorstChild, MiddleChild) error instantiating If the __traits line is uncommented instead, the error is: classAttributeGen.d(22): Error: undefined identifier WorstChild
Re: Array copy warning
Benjamin Thaut: I'm just in the progress of upgrading to dmd 2.063 and I now get the following warnings in my code: Warning: explicit element-wise assignment I am having problems with code like this, that used to work: import std.algorithm: reduce; struct Foo { int x, y; } void main() { Foo[] data = [{10, 20}, {30, 40}]; reduce!((a, b) = a[] += [b.x, b.y][])([0, 0], data); } Now it gives: test.d(5): Error: invalid array operation a[] += [b.x, b.y] (did you forget a [] ?) ...\dmd2\src\phobos\std\algorithm.d(763): Error: template instance test.main.__lambda1!(int[], Foo) error instantiating test.d(5):instantiated from here: reduce!(int[], Foo[]) test.d(5): Error: template instance test.main.reduce!((a, b) = a[] += [b.x, b.y][]).reduce!(int[], Foo[]) error instantiating Expanding the lambda doesn't fully solve the problem: import std.algorithm: reduce; struct Foo { int x, y; } void main() { Foo[] data = [{10, 20}, {30, 40}]; reduce!((a, b) { int[2] c = [b.x, b.y]; a[] += c[]; return c;})([0, 0], data); } Gives: ...\dmd2\src\phobos\std\algorithm.d(763): Warning: explicit slice assignment result = (__lambda1(result, front(_param_1)))[] is better than result = __lambda1(result, front(_param_1)) Bye, bearophile
Re: Starting D with a project in mind.
I've successfully built Pegged and I'm now trying to build vibe.d which requires dub so ... andrew@islay:~$ cd dub-0.9.18/ andrew@islay:~/dub-0.9.18$ ls binbuild-files.txt CHANGELOG.md examples LICENSE_DE.txt package.json source build.cmd build.sh curl.lib installer LICENSE.txt README.md andrew@islay:~/dub-0.9.18$ ./build.sh Generating version file... fatal: Not a git repository (or any parent up to mount point /data) Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set). Running gdmd... source/dub/internal/std/processcompat.d:301: Error: no identifier for declarator args2 source/dub/internal/std/processcompat.d:301: Error: alias cannot have initializer source/dub/internal/std/processcompat.d:315: Error: no identifier for declarator args2 source/dub/internal/std/processcompat.d:315: Error: alias cannot have initializer andrew@islay:~/dub-0.9.18$ Any ideas what I'm doing wrong ? Thanks for all of the hand-holding BTW.
Re: Starting D with a project in mind.
On Tuesday, 15 October 2013 at 12:31:49 UTC, Andrew wrote: Any ideas what I'm doing wrong ? Thanks for all of the hand-holding BTW. What is your GDC version? Looks like one with pre-2.063 front-end as it does not support `alias X = ...` syntax. vibe.d developers do try to support latest two released front-end versions but it is not as easy as it sounds (I hope situation will improve a lot once CI is finally up and running for vibe,d)
Re: Problem: Cannot create class out of nothing using witchcraft
Am 15.10.2013 10:03, schrieb DoctorCaptain: dmd v2.063.2 Hi there! I'm terribly hopeful that you're more interested in the problem at hand than my choice of title. I've been using D for a while as my language of choice for various projects here and there, and I've recently discovered that template programming is magic. This is good. As part of the process of finding anything magic that also works, I've been going completely overboard with it. This involves, among other things, creating empty classes using templates and mixins at compile time, to build an inheritance hierarchy to do fancy things. This is all essentially irrelevant, but brings us to my issue. The next logical step in my adventure here was to see if I could create classes that weren't empty, but in fact has data members, generated at compile time using variadic templates. The first run-through went super well, and I was able to create classes with arbitrary primitive data types. However, ultimately I wanted these compile-time-generated classes with arbitrary data members to have data members that were of the type of the other classes that were also generated at compile time. That is to say, I want to generate, at compile time, classes like this: class MyClass { crazyTemplate!(MagicClassOne).MagicClassOne t1; crazyTemplate2!(MagicClassTwo).MagicClassTwo t2; } such that crazyTemplate and crazyTemplate2 each generate a class definition at compile time, accessible as defined by the string parameter. For example: template crazyTemplate(string classname) { mixin(`class ` ~ className ~ ` {}`); } The bare class-generating templates work, and generating classes that have arbitrary members at compile time using variadic templates given an arbitrary list of basic types works, but as soon as I try to use these template-generated classes as the types of the members of this variadic template, things go awry. I feel like what I'm trying to explain is a bit difficult to parse without a minimal working example, so here is one: code - import std.stdio; import std.typetuple; import std.traits; import std.conv; class BaseClass {} template ChildT(string className) { mixin(`class ` ~ className ~ ` : BaseClass {}`); } template isChildOrBaseClass(T) { enum bool isChildOrBaseClass = is(T : BaseClass); } template GrabBagT(string className, T...) if (allSatisfy!(isChildOrBaseClass, T)) { mixin(genClassStr!(T)(className)); } string genClassStr(T...)(string className) { string classStr = ; classStr ~= `static class ` ~ className ~ ` : BaseClass`; classStr ~= `{`; // Demonstrate that the template itself is not the problem classStr ~= `ChildT!(BestChild).BestChild t1000;`; // Add arbitrary data members foreach (i, TI; T) { // Neither of these work with the generated classes, but the first // will work if GrabBagT is called with primitive types and its // constraint is commented out //classStr ~= fullyQualifiedName!(TI) ~ ` t` ~ to!(string)(i) ~ `;`; //classStr ~= __traits(identifier, TI) ~ ` t` ~ to!(string)(i) ~ `;`; } classStr ~= `void printAttempts() {`; foreach (i, TI; T) { classStr ~= `writeln(` ~ to!string(i) ~ `);`; } classStr ~= `}`; classStr ~= `}`; return classStr; } int main(string[] args) { alias ChildT!(WorstChild).WorstChild WorstChild; alias ChildT!(MiddleChild).MiddleChild MiddleChild; auto magicObject = new GrabBagT!( MagicClass, WorstChild, MiddleChild).MagicClass(); //auto magicObject = new GrabBagT!( //MagicClass, int, float).MagicClass(); magicObject.printAttempts(); return 0; } - That should compile and print out 0 and 1. Note the template constraint that bars the template instantiator from trying to instantiate GrabBagT with anything other than types that can be implicitly treated as type BaseClass. I tried using __traits(identifier) and fullyQualifiedName to get the actual type of the alias passed in (like the BestChild declaration), but the latter gives a mangled name, and the former gives just whatever the bare alias was. In any case. If the fullyQualifiedName line is uncommented, the error is: classAttributeGen.d(22): Error: undefined identifier '__T6ChildTVAyaa10_576f7273744368696c64Z' classAttributeGen.d(22): Error: classAttributeGen.__T6ChildTVAyaa10_576f7273744368696c64Z.WorstChild is used as a type classAttributeGen.d(22): Error: undefined identifier '__T6ChildTVAyaa11_4d6964646c654368696c64Z' classAttributeGen.d(22): Error: classAttributeGen.__T6ChildTVAyaa11_4d6964646c654368696c64Z.MiddleChild is used as a type classAttributeGen.d(54): Error: template instance classAttributeGen.GrabBagT!(MagicClass, WorstChild, MiddleChild) error instantiating If the __traits line is uncommented instead, the error
Re: Problem: Cannot create class out of nothing using witchcraft
Your going way to complicated by actually passing the variadic arguments to the generator function. If you don't pass the variadic arguments to the generator function its way simpler and also works ;-) http://dpaste.dzfl.pl/59e2547b
Re: objects as AA keys
On Tuesday, 15 October 2013 at 05:44:25 UTC, captaindet wrote: hi, i am a bit confused. the official language ref ( http://dlang.org/hash-map.html ) states: Classes can be used as the KeyType. For this to work, the class definition must override the following member functions of class Object: hash_t toHash() bool opEquals(Object) int opCmp(Object) ... but now i stumbled on http://forum.dlang.org/post/mailman.2445.1354457588.5162.digitalmars-d-le...@puremagic.com int[typeof(O)] rc; rc[O] = 42; auto O2 = O; // [...] if (auto r = O2 in rc) return *r; else return rc[O2] = compute(O2); IOW explicitly taking the address may not be necessary when doing that kind of things. and i did a quick test and indeed, it seems to work out of the box - without overriding any member functions. in my use case, i wouldn't be able to modify the class anyway. so my questions: why is it working, is it just syntactic sugar for using cast(void*)Obj as key? what is the danger of using objects as keys? when would it fail? as it seems to be working against language specs, will this 'feature' eventually be removed? (then maybe i should use cast(void*)Obj right away...) thanks, det Do you have an example where it is really working? The problem of not overriding those functions is that maybe you are not getting what you think. For example, the code below will print: [aaa.S:42] [aaa.S:42, aaa.S:43] This is probably not what you want. If you don't override the functions how is the implementation to know what are equivalent keys? Below you would probably expect two S's that are default constructed to hit the same key spot in the AA. But this does not happen since the implementation does not know you want new S to equal new S because there is no opEquals. Thanks, Dan - import std.stdio; class S { int[] o = [1,2,3]; } void main() { S O = new S; int[typeof(O)] rc; rc[O] = 42; writeln(rc); rc[new S] = 43; writeln(rc); }
Re: Problem: Cannot create class out of nothing using witchcraft
On 10/15/13 10:03, DoctorCaptain wrote: If what I am asking is unclear, I will be more than happy to explain in a different way. I tried to be simultaneously as succinct and as comprehensive as possible with what the issue is. I'm not sure what exactly you're trying to do, but... The issue is just that you are trying to access types that are not available inside the GrabBagT template. With /built-in/ types this of course works, as 'int' etc are always known. One way to deal with that would be: template GrabBagT(string className, T...) if (allSatisfy!(isChildOrBaseClass, T)) { mixin(genClassStr!(T.length)(className)); } string genClassStr(size_t TL)(string className) { string classStr = ; classStr ~= `static class ` ~ className ~ ` : BaseClass`; classStr ~= `{`; // Demonstrate that the template itself is not the problem classStr ~= `ChildT!(BestChild).BestChild t1000;`; // Add arbitrary data members foreach (i; 0..TL) classStr ~= T[~ to!(string)(i) ~ `] t` ~ to!(string)(i) ~ `;`; classStr ~= `void printAttempts() {`; foreach (i; 0..TL) classStr ~= `writeln(` ~ to!string(i) ~ `);`; classStr ~= `}`; classStr ~= `}`; return classStr; } artur
should chain be pure
I would like to correctly annotate my functions with pure. I've hit a function that is calling chain which breaks purity. Is chain really not pure? The relevant section of code is: ... auto sortedRage = assumeSorted!(a.when b.when)(opSlice()); auto trisection = sortedRage.trisect(needle); auto ccRate = Rate(0.0); if(trisection[0].length) { ccRate = trisection[0][$-1].value; } foreach(dateRate; chain(trisection[1], trisection[2])) { ... Is there a reasonable work around? Thanks Dan
Re: should chain be pure
Daniel Davidson: I would like to correctly annotate my functions with pure. I've hit a function that is calling chain which breaks purity. Is chain really not pure? Phobos is slowly being annotated with pure/nothrow (and @safe) but not all functions are already tagged. You could fix the problem sending a Phobos patch. Bye, bearophile
Re: should chain be pure
On Tuesday, 15 October 2013 at 13:43:55 UTC, bearophile wrote: Daniel Davidson: I would like to correctly annotate my functions with pure. I've hit a function that is calling chain which breaks purity. Is chain really not pure? Phobos is slowly being annotated with pure/nothrow (and @safe) but not all functions are already tagged. You could fix the problem sending a Phobos patch. Bye, bearophile That is probably beyond my pay-grade at the moment :-) If I just add pure to chain and run unittests all sorts of errors cascade and I don't think I'm in a position to pull it off. If you are agreeing that chain should be pure and it is just following all the calls and making all of them pure, until that happens by the professionals - is there a casting solution so I can fake a pure and move on?
Re: should chain be pure
Daniel Davidson: If you are agreeing that chain should be pure and it is just following all the calls and making all of them pure, until that happens by the professionals - is there a casting solution so I can fake a pure and move on? chain is a template, and in Phobos often templates are not annotated with pure/nothrow, the compiler infers those attributes. Regarding your code, perhaps you can put your call in an impure delegate and than cast it, but D has no direct means to cast purity, because it's highly unsafe and it's against the idea of having purity in the language. So I suggest to replace the pure in your function/method tree with /*pure*/, and later fix the code if/when chains becomes pure. Bye, bearophile
Re: Starting D with a project in mind.
What is your GDC version? Looks like one with pre-2.063 front-end as it does not support `alias X = ...` syntax. vibe.d developers do try to support latest two released front-end versions but it is not as easy as it sounds (I hope situation will improve a lot once CI is finally up and running for vibe,d) I think it's the latest version of GDC :- https://github.com/jpf91/GDC/tree/arm which apparently supports 2.062. In the D community, is there not the concept of stable releases that all tools and libraries support or is it a free for all i.e. nothing works together ? Can I get an earlier version of vibe.d that is compatible with GDC ? I notice that dub must be using a different version of phobos also :- andrew@islay:~/dub/source$ gdmd app.d dub/packagemanager.d:21: Error: module sha is in file 'std/digest/sha.d' which cannot be read Is this something I can update easily ?
Re: Starting D with a project in mind.
On Tuesday, 15 October 2013 at 14:38:32 UTC, Andrew wrote: I think it's the latest version of GDC :- https://github.com/jpf91/GDC/tree/arm which apparently supports 2.062. Ugh, don't know about ARM build but GDC itself currently supports 2.063.2 version for both 4.8 and 4.9 branch. In the D community, is there not the concept of stable releases that all tools and libraries support or is it a free for all i.e. nothing works together ? Can I get an earlier version of vibe.d that is compatible with GDC ? Generally, only latest DMD release + latest library release are guaranteed to work. It is a big and complicated problem to get this right. First, all 3 major compilers have incompatible ABI so they need whole own library stack built starting with druntime / phobos. Second, bigger cross-platform programs like vibe.d have lot of version definitions that change behavior considerably (for example, various event drivers for vibe.d), on top of usual OS / processor versioning. Combined together that creates an exponential configuration count that is almost impossible to test manually. Sonke (vibe.d author) has recently recognized what a disaster this creates and right now adding Continuous Integration testing is high priority target - but this is still work-in-progress. As a result, with every small step from configuration common among library/program developers (usually it is latest DMD + x64_86 + Linux/Windows) probability of something breaking bad is damn high. Actually, I don't know if vibe.d has ever been tested with GDC at all. Is this something I can update easily ? If rebuilding GDC from sources so that it will catch 2.063.2 frontend version is an option - it may help.
Re: Starting D with a project in mind.
On Tuesday, 15 October 2013 at 14:56:06 UTC, Dicebot wrote: On Tuesday, 15 October 2013 at 14:38:32 UTC, Andrew wrote: Is this something I can update easily ? If rebuilding GDC from sources so that it will catch 2.063.2 frontend version is an option - it may help. Looking at https://github.com/jpf91/GDC/commits/arm , 2.063.2 support is also included in the ARM branch, cf. commit 1aa5755 from June 30, so you should have it already I think. Where did you get the 2.062 info from?
Re: Starting D with a project in mind.
Looking at https://github.com/jpf91/GDC/commits/arm , 2.063.2 support is also included in the ARM branch, cf. commit 1aa5755 from June 30, so you should have it already I think. Where did you get the 2.062 info from? 2.062 was mentioned on the GDC website as the latest supported D2. So I'm thoroughly confused then, why won't dub build as it looks as though it didn't support aliases and the phobos library looks as though it has sha1 missing ?
Re: Starting D with a project in mind.
On Tuesday, 15 October 2013 at 18:41:50 UTC, Andrew wrote: Looking at https://github.com/jpf91/GDC/commits/arm , 2.063.2 support is also included in the ARM branch, cf. commit 1aa5755 from June 30, so you should have it already I think. Where did you get the 2.062 info from? 2.062 was mentioned on the GDC website as the latest supported D2. So I'm thoroughly confused then, why won't dub build as it looks as though it didn't support aliases and the phobos library looks as though it has sha1 missing ? Can you check the output for this micro-program on your GDC? ``` pragma(msg, __VERSION__); ```
Re: Starting D with a project in mind.
On Tue, Oct 15, 2013 at 09:19:56PM +0200, Andrew wrote: pragma(msg, __VERSION__); ``` 2060L - seems I'm further advanced than everybody else :-) Wow that's pretty old. The current language version supported by GDC is 2063L. You should probably consider upgrading GDC to at least 2.0.62 (but preferably 2.0.63). Lots of bugs and issues have been fixed since 2.0.60. :) T -- The volume of a pizza of thickness a and radius z can be described by the following formula: pi zz a. -- Wouter Verhelst
Re: Starting D with a project in mind.
2060L - seems I'm further advanced than everybody else :-) Sorry, I thought it was 2.052, but now I see it's well behind since it should be 2.063. I'm rebuilding again from the master.
Re: Starting D with a project in mind.
pragma(msg, __VERSION__); ``` 2060L - seems I'm further advanced than everybody else :-)
Re: Starting D with a project in mind.
On Tuesday, 15 October 2013 at 19:23:13 UTC, Andrew wrote: 2060L - seems I'm further advanced than everybody else :-) Sorry, I thought it was 2.052, but now I see it's well behind since it should be 2.063. I'm rebuilding again from the master. Aha, oops, I have the same 2060L, but that is presumably because I forgot to 'git checkout arm', and the master branch on Johannes' fork is not up-to-date. The reason why this works while normal GDC doesn't is that this is so old it doesn't include some explicit architecture static ifs that were added later (and for which ARM was not available for some time). I'm going to let this stuff rebuild overnight...
Re: objects as AA keys
On 2013-10-15 08:32, Daniel Davidson wrote: On Tuesday, 15 October 2013 at 05:44:25 UTC, captaindet wrote: hi, i am a bit confused. the official language ref ( http://dlang.org/hash-map.html ) states: Classes can be used as the KeyType. For this to work, the class definition must override the following member functions of class Object: hash_t toHash() bool opEquals(Object) int opCmp(Object) ... but now i stumbled on http://forum.dlang.org/post/mailman.2445.1354457588.5162.digitalmars-d-le...@puremagic.com int[typeof(O)] rc; rc[O] = 42; auto O2 = O; // [...] if (auto r = O2 in rc) return *r; else return rc[O2] = compute(O2); IOW explicitly taking the address may not be necessary when doing that kind of things. and i did a quick test and indeed, it seems to work out of the box - without overriding any member functions. in my use case, i wouldn't be able to modify the class anyway. so my questions: why is it working, is it just syntactic sugar for using cast(void*)Obj as key? what is the danger of using objects as keys? when would it fail? as it seems to be working against language specs, will this 'feature' eventually be removed? (then maybe i should use cast(void*)Obj right away...) thanks, det Do you have an example where it is really working? The problem of not overriding those functions is that maybe you are not getting what you think. For example, the code below will print: [aaa.S:42] [aaa.S:42, aaa.S:43] This is probably not what you want. If you don't override the functions how is the implementation to know what are equivalent keys? Below you would probably expect two S's that are default constructed to hit the same key spot in the AA. But this does not happen since the implementation does not know you want new S to equal new S because there is no opEquals. Thanks, Dan in my use case i don't have multiple objects with the same state, so keying them per obj_ptr (if this is what is happening) seems to be sufficient for me. (the object classes are 3rd party so i cannot overwrite member functions anyway.) /det
Re: objects as AA keys
On 10/14/2013 10:44 PM, captaindet wrote: Classes can be used as the KeyType. For this to work, the class definition must override the following member functions of class Object: hash_t toHash() bool opEquals(Object) int opCmp(Object) ... it seems to work out of the box - without overriding any member functions. in my use case, i wouldn't be able to modify the class anyway. so my questions: why is it working, is it just syntactic sugar for using cast(void*)Obj as key? To be pedantic, hash values are of type size_t. what is the danger of using objects as keys? when would it fail? as it seems to be working against language specs, will this 'feature' eventually be removed? (then maybe i should use cast(void*)Obj right away...) I don't know the definitive answer but my experience was the same when I wrote the following chapter: http://ddili.org/ders/d.en/object.html Contrary to your current need, I say However, its default behavior is almost never what is desired. :) thanks, det Ali
Re: Problem: Cannot create class out of nothing using witchcraft
Fixing links: If the template I am trying to instantiate IS NOT variadic, and I pass in an alias of an instantiated template, then the receiving template has all of the type information it needs. Example: dpaste.dzfl.pl/6d618af9 http://dpaste.dzfl.pl/6d618af9 If the template I am trying to instantiate IS variadic, and I pass in a variadic list of aliases of instantiated templates, then the receiving template appears unable to retrieve all of the type information it needs out of each of the indexes of the variadic parameter. We get close with this next example, but the problem appears to be that it tries to create a static array of the tuple T of length i, instead of indexing into it to get the type (but if you provide an i greater than the actual length of the tuple, it complains about going out of bounds of the tuple length, meaning that it IS in fact aware that it's supposed to be indexing into a type tuple): dpaste.dzfl.pl/ff8a5b9d http://dpaste.dzfl.pl/ff8a5b9d And to be absolutely clear, the underlying goal is to generate a class definition at runtime, which I can mix in and then instantiate, that can contain an arbitrary list of data members that are themselves generated at compile time by their own templates. I have demonstrated that it is possible to do this with a single arbitrary template instantiation in dpaste.dzfl.pl/6d618af9 , but as soon as we try to do it with type tuples, it chokes. I am not sure if this is a compiler bug or I'm just out of my mind, but again, for the sake of academic advancement, lets try to solve the problem in complete disregard of whether we should. http://dpaste.dzfl.pl/6d618af9
Re: Problem: Cannot create class out of nothing using witchcraft
On Tuesday, 15 October 2013 at 13:14:46 UTC, Benjamin Thaut wrote: Your going way to complicated by actually passing the variadic arguments to the generator function. If you don't pass the variadic arguments to the generator function its way simpler and also works ;-) http://dpaste.dzfl.pl/59e2547b Thank you for your responses! The following is a modified version of my original post code that incorporates a bit from all the answers I received, and certainly puts me farther along than I was: http://dpaste.dzfl.pl/f7508d25 Taking Benjamin Thaut's suggestion to move the alias's into the global scope, GrabBagT now has access to the types it needs to know about, and my witchcraft abomination of a magic class works as long as everything is available in the same file. However. My original goal, going back to how I want to use this in the project I'm working on, is to define GrabBagT, and the associated templates, in a different file, such that I need only import the file and call: auto magicObject = new GrabBagT!(MagicClass, SomeTypeAlias, SomeOtherTypeAlias).MagicClass(); Which brings us back to the original problem, that passing in aliases to instantiations of templates doesn't work, because the type information is lost. I understand the fundamental issue you folks were bringing up in your posts: GrabBagT cannot possibly actually have access to the real types of the aliases it's receiving, as those types aren't available in its scope (which is why bringing the aliases originally defined within main() out into the global scope makes things work). But then this raises another fundamental issue, as I'm doing this exact thing successfully (passing aliases of template instantiations to other templates), where the only difference is the receiving templates do not have variadic parameters, and I throw the actual template parameter into the mixin itself. That is to say: If the template I am trying to instantiate IS NOT variadic, and I pass in an alias of an instantiated template, then the receiving template has all of the type information it needs. Example: dpaste.dzfl.pl/6d618af9 If the template I am trying to instantiate IS variadic, and I pass in a variadic list of aliases of instantiated templates, then the receiving template appears unable to retrieve all of the type information it needs out of each of the indexes of the variadic parameter. We get close with this next example, but the problem appears to be that it tries to create a static array of the tuple T of length i, instead of indexing into it to get the type (but if you provide an i greater than the actual length of the tuple, it complains about going out of bounds of the tuple length, meaning that it IS in fact aware that it's supposed to be indexing into a type tuple): dpaste.dzfl.pl/ff8a5b9d Given that the compilation error messages in the last DPaste refer to the mixed in code after the class definition string is generated and returned, the issue has to be in the way the type tuple is treated, itself. So, first, the template argument (variadic or otherwise) needs to be part of the STRING that is constructed and passed back to the mixin, so that it can then just naturally access GrabBagT's T type tuple parameter. This is how the non-variadic DPaste example works. Second, the variadic version seems to fail because the type tuple is not indexed correctly, to retrieve the type at that index, because it instead appears to try to make a static array of the whole tuple (which is odd because if you try to index the tuple with an index beyond its length, it suddenly knows it's a type tuple again). And to be absolutely clear, the underlying goal is to generate a class definition at runtime, which I can mix in and then instantiate, that can contain an arbitrary list of data members that are themselves generated at compile time by their own templates. I have demonstrated that it is possible to do this with a single arbitrary template instantiation in dpaste.dzfl.pl/6d618af9 , but as soon as we try to do it with type tuples, it chokes. I am not sure if this is a compiler bug or I'm just out of my mind, but again, for the sake of academic advancement, lets try to solve the problem in complete disregard of whether we should. If any part of my explanation of our current status on this problem is unclear, I would be happy to explain in an alternate way. Thank you again!
cannot call impure function ~this
I get this error: /d701/f223.d(11): Error: pure function 'f223.getA' cannot call impure function 'f223.A.~this' with this code: import std.stdio; struct A { public: ~this() { writeln(DTor); } } A getA() pure nothrow { return A(); } void main() { A a = getA(); writeln(end of main); } But without pure and nothrow I get this output: end of main DTor Why the compiler thinks that the function should/could call A::~this?
Re: how to handle memory ownership when interfacing with C/C++ via internal pointers
On Thursday, 10 October 2013 at 23:02:29 UTC, Timothee Cour wrote: Short version: I have a struct A* aptr allocated in C/C++ with an internal pointer aptr-ptr (say a double*) I want to store a reference x (say double[]) in D to aptr only through aptr-ptr, not through aptr directly as it's inconvenient in my use case. How do I achieve that, so that when x goes out of scope, some deallocator for aptr will be called ? Long version: suppose I have C++ code: struct A{ double*ptr; A(size_t n){ptr=(double*)malloc(n);} ~A(){free(ptr);} }; and a D wrapper around it: extern(C){struct A; A*A_new(size_t n); void A_delete(A*a); double*A_ptr(A*a);} I want to use it as follows: double[] get_x(size_t n){ return A_new(n).A_ptr[0..n]; } void main(){ double[]x=get_x(n); // do something with x; } It's trivial to handle this via a class wrapper: class A2{ A*a; this(size_t n){a=A_new(n);} ~this(){A_delete(n);} double*ptr(){return A_ptr(a);} } double[] get_x(size_t n){ auto a2=new A2(n); return a2.ptr; //this doesn't help much though, A2 will go out of scope when this function exits. } but I don't want to maintain objects of class A2 around, just double[] slices as above. Is there some magic involving core.memory.addRoot,addRange (etc) I can use so that a2 stays alive as long as x stays alive? (in which case when x goes out of scope, 'a2' will too, and will call A_delete). Thanks Ping? Is anything above unclear? here are more details (in a simplified setting): say, I have an image class D_image which has fields: ubyte* ptr //pointer to memory uint[2] size; I'd like to interface with, say, a swig-wrapped opencv C++ image class Swig_image, so that when an object d_image:D_image goes out of scope (and its pointer ptr also goes out of scope), (with d_image constructed from an object swig_image of type Swig_image), then swig_image will also go out of scope. again, this can be done by adding a field to D_image (say of type void* to make it work with any source), buy I'm wondering whether this can be achieved without adding this field, with some GC magic associating a pointer (ptr) to another pointer (cast(void*) swig_image). This would make interfacing with C++ libs much easier as there would be no bookkeeping in user code.
Re: Problem: Cannot create class out of nothing using witchcraft
I missed an extremely critical point. The working example with the single arbitrary template instantiation as a data member of the generated class, http://dpaste.dzfl.pl/6d618af9 , has the template instantiation aliases inside of main, meaning the alias is NOT within the scope of GrabBagT, but it is able to get all of the type information it needs from the alias being passed in. Which reaffirms to me that the problem is not about whether GrabBagT needs to be able to see what the alias refers to (clearly it can figure it out), but that once these aliases are wrapped up into a tuple passed into the variadic version of the template, it stops being able to figure it out. Either the syntax I'm using is wrong, there is a bug in the compiler, or for some reason this extremely specific scenario isn't allowed. In any case, example code that demonstrates the principle we are trying to achieve as working should be able to call magicObject.printSelf() and show that each of its arbitrary data members can call their own printSelf() methods successfully, as with the http://dpaste.dzfl.pl/6d618af9 example, but with an arbitrary list of instantiated templates, instead of just the one. Brain buster, this one.
Re: Starting D with a project in mind.
Aha, oops, I have the same 2060L, but that is presumably because I forgot to 'git checkout arm', and the master branch on Johannes' fork is not up-to-date. The reason why this works while normal GDC doesn't is that this is so old it doesn't include some explicit architecture static ifs that were added later (and for which ARM was not available for some time). I'm going to let this stuff rebuild overnight... My build, from GDC master, went really well until it got to libphobos and then there were many architecture specific bits of code that just didn't include any ARM directives so it's probably currently impossible to build the latest libphobos on ARM. I tried comparing the ARM fork but it was massively different and it looks like libphobos has been mostly rewritten since then. I don't really understand why there are so many .d files that just seem to wrap standard os stuff - why not just use the standard installed C headers and avoid all of this overhead that needs maintaining ? Interestingly the gcc Go compiler that is also included with gcc 4.8 built and installed first time so I'm rather tempted to just to give up with D as this point after a valiant battle for the last few days.
Re: Starting D with a project in mind.
On Tuesday, 15 October 2013 at 22:28:59 UTC, Andrew wrote: I don't really understand why there are so many .d files that just seem to wrap standard os stuff - why not just use the standard installed C headers and avoid all of this overhead that needs maintaining ? Those .d files are essentially just that - ported C headers so that you don't need to declared these functions manually. You can easily re-generated those from actual system C headers using tool like https://github.com/jacob-carlborg/dstep Interestingly the gcc Go compiler that is also included with gcc 4.8 built and installed first time so I'm rather tempted to just to give up with D as this point after a valiant battle for the last few days. Unfortunately, this is an area where difference in developer count is really notable. It is a dead end - support for more exotic platforms like ARM is lacking because there too few people who need it and new bypassers are scared from further investigation because of lacking support. There is hardly anything we can do until some volunteer will appear who is willing to champion this.
Re: Starting D with a project in mind.
P.S. I'd recommend to try to contact Johannes Pfau and ask if he has any plans for updating his ARM Phobos fork to recent version. Such changes should be probably integrated Phobos upstream eventually.
Re: Starting D with a project in mind.
After roughly hacking all of the 'static assert unimplemented' lines in libphobos to just do whatever X86 does, I got it to build and install. Now I'm on 2063L and now hello world builds to 8MB instead of 2MB (although it strips to 760k - twice the previous version). So now I resume my quest to build vibe.d by first trying to build dub and I get :- andrew@islay:~/dub$ ./build.sh Generating version file... Running gdmd... /usr/local/gdc/include/d/4.8.2/armv7l-unknown-linux-gnueabihf/core/time.di:224: error: this cannot be interpreted at compile time, because it has no available source code /usr/local/gdc/include/d/4.8.2/std/net/curl.d:195: note: called from here: dur(2L) line 224 is trying to instantiate a Duration object. Any ideas ?
Re: Starting D with a project in mind.
Unfortunately, this is an area where difference in developer count is really notable. It is a dead end - support for more exotic platforms like ARM is lacking because there too few people who need it and new bypassers are scared from further investigation because of lacking support. There is hardly anything we can do until some volunteer will appear who is willing to champion this. I was hoping to actually learn D before I had to maintain it :-) ARM is hardly exotic, it's the best selling CPU by a large margin. I bet even Microsoft ships more ARM Windows licences than it does Intel now. I'll have a look at that dstep util and see if I can contribute some patches back in order to save some other hapless fool like myself from suffering the same pain. Thanks for your patience supporting me BTW.
Re: [Font] Getting font folder on all platforms
On Friday, 6 September 2013 at 20:54:53 UTC, Flamaros wrote: On Friday, 6 September 2013 at 16:05:43 UTC, Tourist wrote: On Thursday, 5 September 2013 at 19:48:07 UTC, Flamaros wrote: I am searching the right way to find fonts folder for each platforms (Windows, linux, macOS X) On Windows it's generally C:\Windows\Fonts but a direct access seems brutal, it's certainly expected to retrieve this path by using some register keys? Is someone know how it works for linux and/or macOS X? I need to be able to retrieve fastest as possible the right file from the font and family name. Windows: call SHGetKnownFolderPath with FOLDERID_Fonts as rfid. http://msdn.microsoft.com/en-us/library/windows/desktop/bb762188%28v=vs.85%29.aspx Nice, thx. Do you know if there is a table of fonts and there family, or need open all font file my self? I need to do some more tests, but scanning the registry seems working under Windows. Here is my test code : string fontPathFromName(in string name, in Font.Family family = Font.Family.Regular) { version(Windows) { import std.windows.registry; string fontPath = C:/Windows/Fonts/; string fontFileName; Key fontKey; fontKey = Registry.localMachine().getKey(Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts); if (family == Font.Family.Regular) fontFileName = fontKey.getValue(name ~ (TrueType)).value_EXPAND_SZ(); else if (family == Font.Family.Bold) fontFileName = fontKey.getValue(name ~ Bold (TrueType)).value_EXPAND_SZ(); else if (family == Font.Family.Italic) fontFileName = fontKey.getValue(name ~ Italic (TrueType)).value_EXPAND_SZ(); else if (family == (Font.Family.Bold | Font.Family.Italic)) fontFileName = fontKey.getValue(name ~ Bold Italic (TrueType)).value_EXPAND_SZ(); return fontPath ~ fontFileName; } } unittest { assert(fontPathFromName(Arial) == C:/Windows/Fonts/arial.ttf); assert(fontPathFromName(arial) == C:/Windows/Fonts/arial.ttf); // Test with wrong case assert(fontPathFromName(Arial, Font.Family.Bold | Font.Family.Italic) == C:/Windows/Fonts/arialbi.ttf); }
Re: Starting D with a project in mind.
On 10/15/13 3:38 PM, Dicebot wrote: Unfortunately, this is an area where difference in developer count is really notable. It is a dead end - support for more exotic platforms like ARM is lacking because there too few people who need it and new bypassers are scared from further investigation because of lacking support. There is hardly anything we can do until some volunteer will appear who is willing to champion this. I think you mean catch-22 rather than dead-end. There's not more people helping support ARM due to ARM not yet working well, so there's no developers. ARM's not exotic, it's just not on as many people's desktops. Thats been changing rapidly over the last several years.
how to pass multiple arguments via a mixin
is there a general solution to pass multiple arguments to a function via a mixin? see below for a partial solution using Alias, which fails for the last case below: void main(){ import std.stdio; string a=A; string b=B; writeln(a,b);// OK (prints AB) writeln(a,b);//OK (prints both addresses) writeln(mixin(`a,b`));//prints B import std.typetuple; writeln(mixin(`Alias!(a,b)`));//OK:prints AB //writeln(mixin(`Alias!(a,b)`));//CT Error: expression a is not a valid template value argument }
Re: how to pass multiple arguments via a mixin
On Wednesday, 16 October 2013 at 00:36:46 UTC, Timothee Cour wrote: ... Have you tried run-time tuple? ``` import std.typecons; writeln(mixin(tuple(a,b).expand)); ```
Re: Problem: Cannot create class out of nothing using witchcraft
I've gotten extremely close. The DPaste link that follows demonstrates three different templates: The first template is capable of generating the string for and mixing in the definition of a class that has a single arbitrary argument. An object of that class is instantiated, and its printSelf() method is invoked to demonstrate that the arbitrary data member it was generated with is indeed what you would expect it to be. The magic here is fairly plain. The second template is capable of generating the string for the definition of a class that has some arbitrary number of arbitrary arguments at -compile- time, through the use of variadic template parameters. The issue with this string is that the type at T[n], where T is the variadic template parameter, is mangled at compile-time. The data-member-generating foreach loop shows the three potential ways I attempted to get at the full type information. All three have some problem with it, with typeid giving a fully mangled type, fullyQualifiedName giving a mostly mangled type, and __traits(identifier) giving just whatever the alias was that was passed in. The two other commented-out code sections in this template was an attempt to resolve the type information at the time of mixin, rather than within the string generation function, but this doesn't work. The third template demonstrates that D actually can resolve the individual types of the variadic template parameter correctly, so long as it's allowed to do this at runtime. The string printed as a result of instantiating this template shows exactly the class definition we want to be able to mix in at compile time, but this type information eludes us at compile time even though it's clearly readily available at runtime. The code referenced above is here: http://dpaste.dzfl.pl/a6feafc8 I'm not sure why DPaste is failing to compile the code, but I am compiling it with DMD v2.063.2. Also included at the bottom of the DPaste listing is the output I get when running that program, exactly as listed. With all of that said, there is a fundamental difference between how the first template and the second two templates are written. The first one, which works, resolves the T parameter during the mixin. The second two try to resolve the variadic types during class definition string generation. I am pretty convinced at this point that if this is ever going to work, the variadic template parameter type tuple needs to be resolved during the mixin, like with the first example. The how is the question. Again, I attempted to have the variadic template parameter types deduced during execution of the mixin with the two blocks of commented-out code in the second template, but I had no luck there, as I got the same errors as I did in my previous big post. So. By the first template, we know that we can generate class definitions with arbitrary data members and mix them in at compile time using aliases for templated, compile-time-mixin-generated classes, but for each new arbitrary type we want the generated class to have, we need to have a distinct template parameter for the type. By the third template, we know that we should have access to the fully qualified types in the variadic template parameter, but it at least appears to only be fully resolved at runtime (which I feel like is me misunderstanding something, but then that's also the root of our problem). By the second template, we show that trying to deduce the types within the type tuple (the variadic template parameter) during class definition string generation does not work, which leads us to believe it must be resolved while mixing in the class definition using the templated types, but that also doesn't seem to work (as noted by the failed attempts in the two commented out blocks of the second template). I feel like we're so very close to the answer, whether it's Oh, you just have to do this or You're crazy, this is impossible. If only it was possible to summon Andrei. He'd know! Maybe it's some sort of a Bloody Mary thing? Andrei, Andrei, An-
Re: how to pass multiple arguments via a mixin
doesn't work with ref args: void fun(ref int a,ref int b){ a=1; } void main(){ int a,b; import std.typecons; fun(mixin(tuple(a,b).expand)); assert(a==1);//fails } and we can't do a logic such as: if there's ref args use Alias, otherwise use tuple().expand because there could be a mix of the two On Tue, Oct 15, 2013 at 5:56 PM, Dicebot pub...@dicebot.lv wrote: On Wednesday, 16 October 2013 at 00:36:46 UTC, Timothee Cour wrote: ... Have you tried run-time tuple? ``` import std.typecons; writeln(mixin(tuple(a,b).**expand)); ```
how to get a (ref) tuple from a static array ?
how to write a expand function that satisfies the following? void fun(ref int a,ref int b){ a=1; } void main(){ int[2]c; fun(c.expand); assert(c[0]==1); }
Re: Syntax for heap allocated void initialized arrays
On Sat, Sep 21, 2013 at 7:23 AM, bearophile bearophileh...@lycos.comwrote: simendsjo: I'm setting every element in the array, and every field of the element, so I should be safe, right? I think that's sufficiently safe. If the GC run before you have initialized those fields, and some of those fields are references/pointers, that could cause memory leaks until the next time the GC runs. just to clarify: is the following true? int*[N] a=void; foreach(i;N) a[i]=fillValue(i);// some leaks may occur during foreach loop //at the next GC run, no more leaks due to that piece of code Bye, bearophile
Return a const structure by reference.
I'm having trouble trying to return a const reference of a structure. public struct Structure { } public class A { private Structure structure; this(Structure structure) { this.structure = structure; } public ref const Structure getStructure() const { return structure; } } cannot implicitly convert expression (this.structure) of type const(Structure) to Structure
Re: Return a const structure by reference.
On 10/15/2013 09:28 PM, Agustin wrote: I'm having trouble trying to return a const reference of a structure. public struct Structure { } public class A { private Structure structure; this(Structure structure) { this.structure = structure; } public ref const Structure getStructure() const { The two consts up there have exactly the same meaning: Even the first one qualifies the function (more correctly the implicit 'this' reference). You want this: public ref const(Structure) getStructure() const { return structure; } } cannot implicitly convert expression (this.structure) of type const(Structure) to Structure Ali