Taming templates and mixin magic: type inpector helper in D/Phobos?
As a newbie in D (and making a lots of mistakes), I've found myself relying heavily in the use of a rudimentary type inspector to visualize my templated code instantiations. It's simple and incomplete as hell but good enough to see what happens under the hood quickly. QUESTION: Is there a function like that already in D? //real-life example goodEnoughTypeInspector!Human; goodEnoughTypeInspector!(Database!Human); //compile-time output Inspecting type: Human - public string name - public string address - public bool active Inspecting type: Database!(Human) - private string[] name - private string[] address - private bool[] active - public pure nothrow @nogc @safe ulong() count - public void insert
Re: Learning D - modules packages and the package.d
On Wednesday, April 04, 2018 04:54:50 Ali via Digitalmars-d-learn wrote: > I am going through the Learning D book by Michael Parker > So every now and then I will make post about the book > either critics of the book, book content or questions > > > First critic > chapter 2 - the special package module > > this small section, suggest an idiom to create a package which > can have any name > the book suggest somepack > and inside it add a module package.d , so you will end up > somepack/package.d > inside the file add > > > module somepack; //notice this named after the folder > > //then public import std.stdio, somepack.one, somepack.two; > > //etc > > at first i though package.d is special name, as in i must call > the file package.d or this trick or idiom to work > also it felt weird that the module name, is named after the > folder name, which previously was referred to as the package name > > anyway, i started playing with this, and renaming everything > and my conclusion is > > i not really sure, if D really support or have packages > as in D is aware that some modules are together in a package > > it seems to me at this time D only support modules > modules can have names with . in them > you can use the . in module names to make it seem as if its > packages > > > import io = long.module.name > > also seem as a trick that complements having modules with long > names with dots in them > > and it seems you really need to match file and module names > > my critic of the chapter 2 so far, the book doesn't really help > clarify this situation > i am relieved though to learn that D doesnt treat special > file/module names as special In general, modules correspond to files, and packages correspond to folders. That can be played with by naming modules with names that don't match their file names, but it tends to cause problems with build tools. In general, modules and packages should match their corresponding file and folder names if you don't want problems. package.d is a special case. package is not a legal module name, so when the package.d feature was added to the language, the odds of it conflicting with any existing files were very low. What happens with package.d is that when you try to import a package rather than a module, the compiled looks for a package.d file within the package that you're trying to import, and it imports that module. The typical thing to do is to have the module name within that module match the package name. I don't know what happens if you try to do otherwise, but I wouldn't expect it to work, because in this case, the compiler is specifically looking for package.d and not the module with with matching module declaration. _That_ is all that's special about package.d - it's what's imported you try to import a package. Now, if there is a package.d, it's typically the case that it has public import statements for the modules inside the package so that importing the package will then import all of the modules within the package, but what actually gets imported when importing the package is entirely dependent on what's in package.d. It can define symbols of its own, and it doesn't _have_ to publicly import anything. And since public imports can be used in any module, there's nothing really special about them in package.d. It's just that using them in package.d makes it possible to have it be the case that importing a package imports all of the modules within that package. The entire reason that the package.d feature was added to the language was so that a module could be broken up into multiple modules within a package with the same name without breaking code in the process - e.g. std.algorithm, std.container, std.datetime, and std.range were all originally modules, but now, they're all packages. Personally, I don't think that it's great practice to use package.d if you don't have to (and importing that many symbols at once can negatively impact compilation times), but some folks like to use it for their libraries so that you can import everything at once. - Jonathan M Davis
Re: Learning D - modules packages and the package.d
On Wednesday, 4 April 2018 at 04:54:50 UTC, Ali wrote: at first i though package.d is special name, as in i must call the file package.d or this trick or idiom to work the trick was to have one module that public import all the modules you import as group in other modules so instead of importing a dozen or so modules, you only import one module that imports everything you need
Learning D - modules packages and the package.d
I am going through the Learning D book by Michael Parker So every now and then I will make post about the book either critics of the book, book content or questions First critic chapter 2 - the special package module this small section, suggest an idiom to create a package which can have any name the book suggest somepack and inside it add a module package.d , so you will end up somepack/package.d inside the file add module somepack; //notice this named after the folder //then public import std.stdio, somepack.one, somepack.two; //etc at first i though package.d is special name, as in i must call the file package.d or this trick or idiom to work also it felt weird that the module name, is named after the folder name, which previously was referred to as the package name anyway, i started playing with this, and renaming everything and my conclusion is i not really sure, if D really support or have packages as in D is aware that some modules are together in a package it seems to me at this time D only support modules modules can have names with . in them you can use the . in module names to make it seem as if its packages import io = long.module.name also seem as a trick that complements having modules with long names with dots in them and it seems you really need to match file and module names my critic of the chapter 2 so far, the book doesn't really help clarify this situation i am relieved though to learn that D doesnt treat special file/module names as special
Re: is this even possible? newbie + mixin template + foreach (allMembers)
On Tuesday, 3 April 2018 at 18:49:00 UTC, Carlos Navarro wrote: QUESTION: Obviously I'm no geting mixins/templates nor traits and I'm failing miserably to find/identify the right examples or documentation to help me tackle this thing. What is wrong in this code? is this pattern sintactically possible? what I'm getting wrong? [...] ICEs (compiler segfault) should _always_ be reported on Bugzilla. The compiler should never ever segfault - even on invalid code. I just did so for you: https://issues.dlang.org/show_bug.cgi?id=18718
Re: Better way to append to array than ~= ?
On Tuesday, 3 April 2018 at 20:02:46 UTC, Vladimirs Nordholm wrote: On Tuesday, 3 April 2018 at 19:53:11 UTC, Meta wrote: On Tuesday, 3 April 2018 at 19:02:25 UTC, Vladimirs Nordholm wrote: [...] In this specific case, since you know the length of `Args`, you can pre-allocate an array of that size and loop through it doing your initialization. However, if you want really performant code, you should allocate a static array on the stack outside of the function and pass it in as a buffer. I don't think I know the size of the arguments. If I pass in "123" and MySpecialType('a'), the result should be: assert(foo("123", MySpecialType('a')) == [MySpecialType('1'), MySpecialType('2'), MySpecialType('3'), MySpecialType('a')]); What should the length of the pre-allocated array be? In my try, I iterate the args twice. The first time to calculate the number of elements, then preallocate and then iterate them again and constructing the proper objects. It is not nice, but about 1/3 of time, compared to original version, compiled in release mode. https://run.dlang.io/is/E6ckog
Re: Better way to append to array than ~= ?
On Tuesday, 3 April 2018 at 20:02:46 UTC, Vladimirs Nordholm wrote: On Tuesday, 3 April 2018 at 19:53:11 UTC, Meta wrote: On Tuesday, 3 April 2018 at 19:02:25 UTC, Vladimirs Nordholm wrote: [...] In this specific case, since you know the length of `Args`, you can pre-allocate an array of that size and loop through it doing your initialization. However, if you want really performant code, you should allocate a static array on the stack outside of the function and pass it in as a buffer. I don't think I know the size of the arguments. If I pass in "123" and MySpecialType('a'), the result should be: assert(foo("123", MySpecialType('a')) == [MySpecialType('1'), MySpecialType('2'), MySpecialType('3'), MySpecialType('a')]); What should the length of the pre-allocated array be? You know the static types of the arguments, so it is not impossible. However, the more flexible you need to be, the more complex your code will have to be, and it probably won't be worth the added complexity. Anyway, sorry for derailing a bit. That's not really your question. Using Appender!MySpecialType might be marginally faster than ~=, but from the looks of it you are already using Appender. I don't know if there's much more you can do to speed up appending without just rolling your own solution or restructuring your code.
Re: Better way to append to array than ~= ?
On Tuesday, 3 April 2018 at 19:53:11 UTC, Meta wrote: On Tuesday, 3 April 2018 at 19:02:25 UTC, Vladimirs Nordholm wrote: [...] In this specific case, since you know the length of `Args`, you can pre-allocate an array of that size and loop through it doing your initialization. However, if you want really performant code, you should allocate a static array on the stack outside of the function and pass it in as a buffer. I don't think I know the size of the arguments. If I pass in "123" and MySpecialType('a'), the result should be: assert(foo("123", MySpecialType('a')) == [MySpecialType('1'), MySpecialType('2'), MySpecialType('3'), MySpecialType('a')]); What should the length of the pre-allocated array be?
Re: mixin break; in switch containing static foreach
On Tuesday, 3 April 2018 at 19:41:54 UTC, Alex wrote: On Tuesday, 3 April 2018 at 19:31:50 UTC, Vladimirs Nordholm wrote: [...] Would labelling help? https://run.dlang.io/is/vE1KyD Ah! Okay, now I see. Thanks Alex and Adam!
Re: Better way to append to array than ~= ?
On Tuesday, 3 April 2018 at 19:02:25 UTC, Vladimirs Nordholm wrote: Hello people. I currently have a function which multiple times per second takes in arguments, and appends the argument as my special type. The following code should explain what I do more properly: struct MySpecialType { char c; } auto foo(Args...)(Args args) { MySpecialType[] bar; foreach(ref arg; args) { static if(is(typeof(arg) == MySpecialType)) { bar ~= arg; } else { foreach(c; to!string(arg)) { bar ~= MySpecialType(c); } } } // do more stuff } Now, from my trace.log, some of the topmost things on the timing list are `std.array.Appender!(immutable(char).stuff>`. I also remember reading some years ago that ~= isn't optimal for speed. So my question is: Is there a better and/or faster way of doing this, or is this the best approach? In this specific case, since you know the length of `Args`, you can pre-allocate an array of that size and loop through it doing your initialization. However, if you want really performant code, you should allocate a static array on the stack outside of the function and pass it in as a buffer.
Re: mixin break; in switch containing static foreach
On Tuesday, 3 April 2018 at 19:31:50 UTC, Vladimirs Nordholm wrote: switch(foo) Put the label on the switch whatever: switch(foo) mixin(format(" case Foo.%s:bar = Bar.%s;break; ", f, f)); then use the label here break whatever;
Re: mixin break; in switch containing static foreach
On Tuesday, 3 April 2018 at 19:31:50 UTC, Vladimirs Nordholm wrote: My base problem is that I want to mixin `break` into a switch statement, but the mixin is within a static foreach. Take a look at the following code: switch(foo) { static foreach(f; EnumMembers!Foo) { mixin(format(" case Foo.%s:bar = Bar.%s;break; ", f, f)); } default: /* do stuff */; break; } The above code returns the error "Error: must use labeled `break` within `static foreach`". For a more complete example, take a look att this sample code: https://dpaste.dzfl.pl/f3ab6d9679fc I also attempted this solution, but I got the error that the label didn't exist. (And it looks pretty ugly) mixin(format("%s: case Foo.%s: abc = Foo.X%s; break %s;", f, f, f, f)); Any of you have a solution for this problem? Best regards, Vladimirs Nordholm Would labelling help? https://run.dlang.io/is/vE1KyD
mixin break; in switch containing static foreach
My base problem is that I want to mixin `break` into a switch statement, but the mixin is within a static foreach. Take a look at the following code: switch(foo) { static foreach(f; EnumMembers!Foo) { mixin(format(" case Foo.%s:bar = Bar.%s;break; ", f, f)); } default: /* do stuff */; break; } The above code returns the error "Error: must use labeled `break` within `static foreach`". For a more complete example, take a look att this sample code: https://dpaste.dzfl.pl/f3ab6d9679fc I also attempted this solution, but I got the error that the label didn't exist. (And it looks pretty ugly) mixin(format("%s: case Foo.%s: abc = Foo.X%s; break %s;", f, f, f, f)); Any of you have a solution for this problem? Best regards, Vladimirs Nordholm
Re: is this even possible? newbie + mixin template + foreach (allMembers)
On Tuesday, 3 April 2018 at 18:57:29 UTC, WebFreak001 wrote: you need to use a static foreach for this. You can insert a static foreach basically where you can insert a function definition like void foo() {} foreach is more like a function call like foo(), so you can't put it in the mixin template. A mixin template is basically expected to be mixin-able in global scope or in a class/struct so it can't have any things like function calls because that would be the same as writing `foo();` at global level instead of in the main function. static foreach on the other hand allows exactly that because it literally unrolls the contents and inserts it multiple times, so you can also put it in mixin templates if the content of the loop is valid in mixin templates. If you need to support older compilers you can use normal foreach with ctfe by generating a code string or do recursive templates, but I would really encourage you to use static foreach instead, it is cleaner and faster. I think, the OP has something other in mind. Look at this: ´´´ void main(){} struct World { floatrotation; bool active; //mixin BuildStuff!(); } mixin BuildStuff!(); mixin template BuildStuff() { static foreach(elem; __traits(allMembers, World)) { pragma(msg, elem); } } ´´´ While the outer mixin works as expected, the inner one results in a seg fault. No idea why, however, too...
Better way to append to array than ~= ?
Hello people. I currently have a function which multiple times per second takes in arguments, and appends the argument as my special type. The following code should explain what I do more properly: struct MySpecialType { char c; } auto foo(Args...)(Args args) { MySpecialType[] bar; foreach(ref arg; args) { static if(is(typeof(arg) == MySpecialType)) { bar ~= arg; } else { foreach(c; to!string(arg)) { bar ~= MySpecialType(c); } } } // do more stuff } Now, from my trace.log, some of the topmost things on the timing list are `std.array.Appender!(immutable(char).`. I also remember reading some years ago that ~= isn't optimal for speed. So my question is: Is there a better and/or faster way of doing this, or is this the best approach?
Re: is this even possible? newbie + mixin template + foreach (allMembers)
On Tuesday, 3 April 2018 at 18:49:00 UTC, Carlos Navarro wrote: QUESTION: Obviously I'm no geting mixins/templates nor traits and I'm failing miserably to find/identify the right examples or documentation to help me tackle this thing. What is wrong in this code? is this pattern sintactically possible? what I'm getting wrong? CONTEXT: I'm a newbie trying to extend a struct using a mixin template like this one: struct World { floatrotation; bool active; mixin BuildStuff; } mixin template BuildStuff() { foreach(elem; __traits(allMembers, typeof(this))) { //pragma(msg, elem); } } //full example here: https://run.dlang.io/is/OeXS4j COMPILER OUTPUT: 2.067.1 to 2.071.2: Failure with output: - onlineapp.d(18): Error: declaration expected, not 'foreach' onlineapp.d(18): Error: declaration expected, not '__traits' onlineapp.d(22): Error: template member expected - 2.072.2 to 2.075.1: Failure with output: - onlineapp.d(18): Error: declaration expected, not 'foreach' onlineapp.d(18): Error: declaration expected, not '__traits' onlineapp.d(22): Error: matching '}' expected, not EOF - Since 2.076.1: Segfault and no output you need to use a static foreach for this. You can insert a static foreach basically where you can insert a function definition like void foo() {} foreach is more like a function call like foo(), so you can't put it in the mixin template. A mixin template is basically expected to be mixin-able in global scope or in a class/struct so it can't have any things like function calls because that would be the same as writing `foo();` at global level instead of in the main function. static foreach on the other hand allows exactly that because it literally unrolls the contents and inserts it multiple times, so you can also put it in mixin templates if the content of the loop is valid in mixin templates. If you need to support older compilers you can use normal foreach with ctfe by generating a code string or do recursive templates, but I would really encourage you to use static foreach instead, it is cleaner and faster.
Re: @property for simple methods?
On Monday, 2 April 2018 at 15:05:04 UTC, Seb wrote: On Monday, 2 April 2018 at 14:51:57 UTC, Vladimirs Nordholm wrote: On Monday, 2 April 2018 at 14:20:49 UTC, Dennis wrote: [...] Ah! First time I read the docs I didn't understand the typeof(exp) explanation, but yours made me understand that part. Do you think I should I omit the @property tag, if the only wanted behaviour is to set a value (`foo.bar = "baz";`) ? Yes I would omit @proporty if you don't need it as it isn't really useful at the moment. There's a DIP to fix it and make it more powerful though: https://github.com/dlang/DIPs/pull/97 And if you are looking for @read, @write limitations the accessors library might be interesting to you: https://code.dlang.org/packages/accessors Nice read, and the library seems interesting
is this even possible? newbie + mixin template + foreach (allMembers)
QUESTION: Obviously I'm no geting mixins/templates nor traits and I'm failing miserably to find/identify the right examples or documentation to help me tackle this thing. What is wrong in this code? is this pattern sintactically possible? what I'm getting wrong? CONTEXT: I'm a newbie trying to extend a struct using a mixin template like this one: struct World { floatrotation; bool active; mixin BuildStuff; } mixin template BuildStuff() { foreach(elem; __traits(allMembers, typeof(this))) { //pragma(msg, elem); } } //full example here: https://run.dlang.io/is/OeXS4j COMPILER OUTPUT: 2.067.1 to 2.071.2: Failure with output: - onlineapp.d(18): Error: declaration expected, not 'foreach' onlineapp.d(18): Error: declaration expected, not '__traits' onlineapp.d(22): Error: template member expected - 2.072.2 to 2.075.1: Failure with output: - onlineapp.d(18): Error: declaration expected, not 'foreach' onlineapp.d(18): Error: declaration expected, not '__traits' onlineapp.d(22): Error: matching '}' expected, not EOF - Since 2.076.1: Segfault and no output
Re: @property for simple methods?
On Monday, 2 April 2018 at 15:15:05 UTC, Dennis wrote: On Monday, 2 April 2018 at 14:51:57 UTC, Vladimirs Nordholm wrote: Do you think I should I omit the @property tag, if the only wanted behaviour is to set a value (`foo.bar = "baz";`) ? You're probably fine either way, it's mostly for making your intention clear. Jonathan M Davis made a great explanation: (https://forum.dlang.org/post/mailman.709.1481234980.9448.digitalmars-d-le...@puremagic.com) His reasoning is the same as mine. I only have the @property as documentation :)
Second Language Acquisition - Dogme & Direct Method
The Dogme method, based on the writing of Scott Thornbury, “considers language learning to be a process where language emerges rather than one where it is acquired”. The entire method is based on conversation and the teaching (or in group lessons ‘moderation’) as such does not follow specific syllabus. While there is considerable criticism on this method (especially if followed strictly avoiding all text-material), interestingly it represents an excellent example of point (B) highlighted above – tapping into “Primary Language Acquisition Process Methods”. Also in Children Primary Language Acquisition very little text-material is used. (Picture-)Books are material to support a learning process entirely based on conversation. Almost every person went through this apparently highly effective process; the efficiency of this approach for Adult Education depends on the overall curriculum (eg intensity of program, frequency of lessons, setup of lessons). To elaborate on the efficiency it has to be noted that Children follow this approach over 1-2 years fulltime (in the “direct method”, see below). Furthermore the method was developed with very specific (e.g. non-tonal) languages in mind. Learning for example Chinese without basic graphical illustrations of tones or letters might be challenging. www.language-school.sg
Re: How to Stay Away From Faux Pas in a Foreign Language?
On Tuesday, 3 April 2018 at 15:02:34 UTC, markmst wrote: Why Pay For Learning a Foreign I actually read this until "Why Pay For Learning a Foreign Language". I didn't get the joke... Go figure..
How to Stay Away From Faux Pas in a Foreign Language?
Many language learners will have a similar story to narrate. They have often used a foreign word accidentally, which may sound similar in the English as well as in the target language and yet are completely different in their meanings, Such linguistic goof-ups are referred to as "false friends". When you are learning a new language, there is hardly a strategic way to identify your false friends. The reason for that is they occur without any set patterns and mostly due to coincidence. For instance, in the Portuguese language, when your superior volunteers to assist in your office presentation, it signifies that they will not assist but observe it. On several occasions, certain words of a foreign language may appear funny to a person who is not aware of it, especially on a menu at a restaurant. But it is still important to resist the temptation of laughing out loud Why Pay For Learning a Foreign Language at that local language. The reason for that is the locals around you will consider it extremely rude. Try to speak at a slow and measured pace, especially when you are travelling between two countries. You need to give adequate time between your mouth and brain to ensure that you are not using the wrong language in the wrong country. When you learn to avoid these common mistakes while speaking a foreign language, you can enjoy a fabulous time. Plus, you can pick up quite a few lingo while not offending the locals. More information on : www.language-school.hk
Re: Why toUTF8 not accept wchar[] as argument?
On Tuesday, 3 April 2018 at 13:12:05 UTC, Timoses wrote: On Tuesday, 3 April 2018 at 05:20:55 UTC, Seb wrote: Better diagnostics and error messages is a key goal in 2018 for dmd ;-) Awesome! How about telling the user which of the template constraints failed? Would be so awesome. Currently, there's a need to check every single one (as mentioned by bauss) which can sometimes be a hassle. I guess related issues are: https://issues.dlang.org/show_bug.cgi?id=9626 https://issues.dlang.org/show_bug.cgi?id=4970
Re: Why toUTF8 not accept wchar[] as argument?
On Tuesday, 3 April 2018 at 05:20:55 UTC, Seb wrote: Better diagnostics and error messages is a key goal in 2018 for dmd ;-) Awesome! How about telling the user which of the template constraints failed? Would be so awesome. Currently, there's a need to check every single one (as mentioned by bauss) which can sometimes be a hassle.
Re: What is the equivalent of C++'s std::optional and std::nullopt in D?
On Tuesday, 3 April 2018 at 02:10:09 UTC, helxi wrote: For reference: https://en.cppreference.com/w/cpp/utility/optional See also this topic recently discussed: https://forum.dlang.org/post/p9qvb8$1j1n$1...@digitalmars.com
Re: How to destruct class instances allocated by a Region-allocator over a single GC block
On Monday, 2 April 2018 at 21:32:47 UTC, Steven Schveighoffer wrote: On 4/2/18 5:16 PM, Per Nordlöw wrote: On Monday, 2 April 2018 at 20:43:01 UTC, Alexandru Jercaianu wrote: I am not completely sure how to solve this, but maybe we can find some clues here [1]. It seems like we should use addRoot on the buffer returned by GC.instance.allocate to keep it alive. Then, we can use addRange on each node after allocation and somehow use 'TypeInfo' to trigger destructors. I'll dig into this more tomorrow and come back with a better answer. How can there not be a documented answer for this question, given that std.experimental.allocator has been in Phobos for 2 years? Has std.experimental.allocator only been used for allocating `struct`s? Is the Region allocator especially misfit for constructing classes? Since a while, the GC also calls struct destructors, so it's likely to be a problem for both. Note, addRoot and addRange will NOT call the destructors appropriately. It will just prevent those memory areas from getting collected. The memory shouldn't be collected anyway because RegionAllocator should have a reference to it. The only way it will get destroyed is removing the root/range, and then it will get collected just like any other GC block -- same as it is now. It looks like std.experimental.allocator assumes you will manually destroy items (possibly via dispose), it has no mechanism to say "here's how to destroy this memory I'm allocating if you happen to collect it". -Steve The GCAllocator from std.experimental uses the druntime core.memory.GC, and allocates with a call to GC.malloc [1] The GC doesn't know how you are using the memory chunk that he provided you with. He only keeps a track of this chunk and will collect it when there are no more references to it; you could also manually free it, if you wish so, with a call to `GCAllocator.instance.deallocate`. As Steve has said, you will have to manually destroy the items. I recommend using dispose as it checks if the destroyed object has an explicit destructor, which it calls, before deallocating the memory. So, say `reg` is your allocator, your workflow would be auto obj = reg.make!Type(args); /* do stuff */ reg.dispose(obj); // If Type has a __dtor, it will call obj.__dtor // and then reg.deallocate(obj) Hope this helps. Cheers, Edi [1] - https://dlang.org/library/core/memory/gc.malloc.html