Re: Anonymous nogc class
On Thursday, 7 September 2017 at 23:40:11 UTC, Jiyan wrote: Hey, wanted to know whether it is possible to make anonymous nogc classes: interface I { public void ap(); } void exec(I i) { i.ap; } // now execute, but with something like `scope` exec( new class I { int tr = 43; override void ap(){tr.writeln;} }); Thanks :) Sadly, even std.typecons.scoped isn't currently @nogc: https://issues.dlang.org/show_bug.cgi?id=13972 https://issues.dlang.org/show_bug.cgi?id=17592 This can be worked around by casting scoped's destructor to be @nogc, but that's a heavy-handed approach that ruins type safety, and is the wrong solution in non-@nogc situations. Should you want to, this is what it should look like: ~this() { (cast(void delegate(T) @nogc)((T t){ // `destroy` will also write .init but we have no functions in druntime // for deterministic finalization and memory releasing for now. .destroy(t); }))(Scoped_payload); } If and when this issue is resolved, this should work: interface I { public void ap(); } void exec(I i) { i.ap; } auto scopedAnon(T)(lazy T dummy) if (is(T == class)) { import std.typecons; return scoped!T(); } unittest { auto i = scopedAnon(new class I { int tr = 43; override void ap() { import std.stdio; tr.writeln; } }); exec(i); } -- Biotronic
Re: Container Array
On Thursday, 7 September 2017 at 20:47:43 UTC, Ali Çehreli wrote: On 09/07/2017 10:39 AM, Vino.B wrote: > Array!(Tuple!(string, ulong)) coSizeDirList () { You stated the return type explicitly above. > return tuple (dFiles[], Subdata[]); According to the error message, what is being returned does not have the same type: > Test1.d(27): Error: cannot implicitly convert expression > (tuple(dFiles.opSlice(), Subdata.opSlice())) of type > Tuple!(RangeT!(Array!(Tuple!string)), RangeT!(Array!ulong)) to > Array!(Tuple!(string, ulong)) The actual return type is Tuple!(RangeT!(Array!(Tuple!string)), RangeT!(Array!ulong)) There needs to be some transformations to match the two. Ali Hi Ali, At last was able to print the output, but i am getting some "Deprecation" warnings like below and also can you help me in formating the output to display ulong. Output: Size.d(9): Deprecation: std.container.array.RangeT(A) is not visible from module Size Size.d(9): Deprecation: std.container.array.RangeT(A) is not visible from module Size Size.d(9): Deprecation: std.container.array.RangeT(A) is not visible from module Size Size.d(9): Deprecation: std.container.array.RangeT(A) is not visible from module Size [Tuple!string("C:\\Temp\\sapnas2\\BACKUP\\dir1"), Tuple!string("C:\\Temp\\sapnas2\\BACKUP\\DND3"), Tuple!string("C:\\Temp\\sapnas2\\BACKUP\\DND5")][34, 4] Program: import std.algorithm: filter, map, fold; import std.container; import std.file: SpanMode, dirEntries, isDir; import std.stdio: File, writefln, writeln; import std.typecons: tuple, Tuple; import std.parallelism: parallel; import std.conv; import std.range; Tuple!(RangeT!(Array!(Tuple!string)), RangeT!(Array!ulong)) coSizeDirList () { string FFs = "C:\\Temp\\sapnas2\\BACKUP"; int SizeDir = 1; ulong subdirTotal; ulong subdirTotalGB; Array!(ulong) Subdata; auto dFiles = Array!(Tuple!(string)) (dirEntries(FFs, SpanMode.shallow).filter!(a => a.isDir).map!(a => tuple(a.name))); foreach (d; dFiles[]) { auto SdFiles = Array!(Tuple!(ulong)) (dirEntries(d[0], SpanMode.depth).map!(a => tuple(a.size))); foreach(f; SdFiles[]) { subdirTotal += f.fold!((a, b) => a + b); } subdirTotalGB = (subdirTotal/1024/1024); if (subdirTotalGB > SizeDir) { Subdata ~= subdirTotalGB; } subdirTotal = 0; } return tuple (dFiles[], Subdata[]); } void main () { writeln(coSizeDirList[]); //writefln("%(%-(%-63s %)\n%)", coSizeDirList[]); }
Re: D is Multiplatform[DUVIDA]
On Friday, 8 September 2017 at 03:56:25 UTC, rikki cattermole wrote: On 08/09/2017 3:08 AM, dark777 wrote: On Friday, 8 September 2017 at 00:09:08 UTC, solidstate1991 wrote: On Thursday, 7 September 2017 at 23:58:05 UTC, dark777 wrote: Good night, did you want to know this? Is the DE language cross-platform or cross-compile like C ++? GDC and LDC has multi-platform support, I'm currently working on an ARM backend for DMD. so does it mean that if I develop a program using the D language in BSD creating generic resources for example and compiling on windows, linux and darwin it would work fine? Each platform has its own unique behavior and related code. Gotta try it to know for certain. But that is unrelated to D in the most part :) but in any case then the D language can be considered multiplatform?
Re: D is Multiplatform[DUVIDA]
On 08/09/2017 3:08 AM, dark777 wrote: On Friday, 8 September 2017 at 00:09:08 UTC, solidstate1991 wrote: On Thursday, 7 September 2017 at 23:58:05 UTC, dark777 wrote: Good night, did you want to know this? Is the DE language cross-platform or cross-compile like C ++? GDC and LDC has multi-platform support, I'm currently working on an ARM backend for DMD. so does it mean that if I develop a program using the D language in BSD creating generic resources for example and compiling on windows, linux and darwin it would work fine? Each platform has its own unique behavior and related code. Gotta try it to know for certain. But that is unrelated to D in the most part :)
Re: D is Multiplatform[DUVIDA]
On Friday, 8 September 2017 at 00:09:08 UTC, solidstate1991 wrote: On Thursday, 7 September 2017 at 23:58:05 UTC, dark777 wrote: Good night, did you want to know this? Is the DE language cross-platform or cross-compile like C ++? GDC and LDC has multi-platform support, I'm currently working on an ARM backend for DMD. so does it mean that if I develop a program using the D language in BSD creating generic resources for example and compiling on windows, linux and darwin it would work fine?
Re: D is Multiplatform[DUVIDA]
On Thursday, 7 September 2017 at 23:58:05 UTC, dark777 wrote: Good night, did you want to know this? Is the DE language cross-platform or cross-compile like C ++? GDC and LDC has multi-platform support, I'm currently working on an ARM backend for DMD.
D is Multiplatform[DUVIDA]
Good night, did you want to know this? Is the DE language cross-platform or cross-compile like C ++?
Re: Is compiling for Android/iOS possible?
On Wednesday, 6 September 2017 at 18:34:28 UTC, Timothy Foster wrote: I'm just wondering if I made an application for Windows/Mac/Linux if I could get it to also work on mobile devices, or would I have to rewrite the application in another language to get it to work? If it's possible, what should I be looking at to get something like a "Hello World" example to show on my phone using D? For iOS, there's this: https://github.com/smolt/ldc-iphone-dev I'm not sure if it's production ready though.
Anonymous nogc class
Hey, wanted to know whether it is possible to make anonymous nogc classes: interface I { public void ap(); } void exec(I i) { i.ap; } // now execute, but with something like `scope` exec( new class I { int tr = 43; override void ap(){tr.writeln;} }); Thanks :)
Re: New programming paradigm
On Thursday, 7 September 2017 at 16:55:02 UTC, EntangledQuanta wrote: Sorry, I think you missed the point completely... or I didn't explain things very well. I don't think I did - your new explanation didn't change my understanding at least. This indicates I'm the one who's bad at explaining. Ah well. The point of my post was mostly to rewrite the code you'd posted in a form that I (and, I hope, others) found easier to understand. I see no where in your code where you have a variant like type. True. I've now rewritten it to use std.variant.Algebraic with these semantics: auto foo(T1, T2)(T1 a, T2 b, int n) { import std.conv; return T1.stringof~": "~to!string(a)~" - "~T2.stringof~": "~to!string(b); } unittest { import std.variant; Algebraic!(float, int) a = 4f; Algebraic!(double, byte) b = 1.23; auto res = varCall!foo(a, b, 3); assert(res == "float: 4 - double: 1.23"); } template varCall(alias fn) { import std.variant; auto varCall(int n = 0, Args...)(Args args) { static if (n == Args.length) { return fn(args); } else { auto arg = args[n]; static if (is(typeof(arg) == VariantN!U, U...)) { foreach (T; arg.AllowedTypes) { if (arg.type == typeid(T)) return varCall!(n+1)(args[0..n], arg.get!T, args[n+1..$]); } assert(false); } else { return varCall!(n+1)(args); } } } } Sadly, by using std.variant, I've given up on the elegant switch/case in exchange for a linear search by typeid. This can be fixed, but requires changes in std.variant. Of course, it would be possible to hide all this behind compiler magic. Is that desirable? I frankly do not think so. We should be wary of adding too much magic to the compiler - it complicates the language and its implementation. This is little more than an optimization, and while a compiler solution would be less intrusive and perhaps more elegant, I do not feel it provides enough added value to warrant its inclusion. Next, I'm curious about this code: void bar(var t) { writeln("\tbar: Type = ", t.type, ", Value = ", t); } void main() { bar(3); // calls bar as if bar was `void bar(int)` bar(3.4f); // calls bar as if bar was `void bar(float)` bar("sad"); // calls bar as if bar was `void bar(string)` } What does 'var' add here, that regular templates do not? (serious question, I'm not trying to shoot down your idea, only to better understand it) One possible problem with var here (if I understand it correctly) would be separate compilation - a generated switch would need to know about types in other source files that may not be available at the time it is compiled. Next: var foo(var x) { if (x == 3) return x; return "error!"; } This looks like a sort of reverse alias this, which I've argued for on many occasions. Currently, it is impossible to implement a type var as in that function - the conversion from string to var would fail. A means of implementing this has been discussed since at least 2007, and I wrote a DIP[1] about it way back in 2013. It would make working with variants and many other types much more pleasant. [1]: https://wiki.dlang.org/DIP52
Re: performance cost of sample conversion
On Thursday, 7 September 2017 at 05:45:58 UTC, Ali Çehreli wrote: You have to measure. Indeed. Here's a start: The program has way too many things pre-defined, and the semantics are such that workWithDoubles can be completely eliminated... So you are not measuring what you want to be measuring. Make stuff depend on argc, and print the result of calculations or do something else such that the calculation must be performed. When measuring without LTO, probably attaching @weak onto the workWith* functions will work too. (pragma(inline, false) does not prevent reasoning about the function) -Johan
Re: One path skips constructor - is this a bug?
On Thursday, 7 September 2017 at 16:08:53 UTC, Piotr Mitana wrote: main.d(17): Error: one path skips constructor main.d(15): Error: return without calling constructor http://www.digitalmars.com/d/archives/digitalmars/D/learn/Throwing_exception_in_constructor_28995.html
Re: New programming paradigm
On Thursday, 7 September 2017 at 19:33:01 UTC, apz28 wrote: On Thursday, 7 September 2017 at 17:13:43 UTC, EntangledQuanta wrote: On Thursday, 7 September 2017 at 15:36:47 UTC, Jesse Phillips wrote: [...] All types have a type ;) You specified in the above case that m is an int by setting it to 4(I assume that is what var(4) means). But the downside, at least on some level, all the usable types must be know or the switch cannot be generated(there is the default case which might be able to solve the unknown type problem in some way). [...] Nice for simple types but fail for struct, array & object Current variant implementation is lack of type-id to check for above ones. For this lacking, is there a runtime (not compile time - trait) to check if a type is a struct or array or object? Cheer On Thursday, 7 September 2017 at 19:33:01 UTC, apz28 wrote: On Thursday, 7 September 2017 at 17:13:43 UTC, EntangledQuanta wrote: On Thursday, 7 September 2017 at 15:36:47 UTC, Jesse Phillips wrote: [...] All types have a type ;) You specified in the above case that m is an int by setting it to 4(I assume that is what var(4) means). But the downside, at least on some level, all the usable types must be know or the switch cannot be generated(there is the default case which might be able to solve the unknown type problem in some way). [...] Nice for simple types but fail for struct, array & object Current variant implementation is lack of type-id to check for above ones. For this lacking, is there a runtime (not compile time - trait) to check if a type is a struct or array or object? Cheer No, it is not a big deal. One simply has to have a mapping, it doesn't matter what kind of type, only that it exists at compile time. It can be extended to be used with any specific type. One will need to be able to include some type information in the types that do not have them though, but that only costs a little memory. The point is not the exact method I used, which is just fodder, but that if the compiler implemented such a feature, it would be very clean. I left, obviously, a lot of details out that the compiler would have to due. In the protoypes, you see that I included an enum... the enum is what does the work... it contains type information. enum types { Class, Float, Int, MySpecificClass, } the switch then can be used and as long as the actual values 'typeid' matches, it will link up with the template. You can't use types directly, that would be pointless, they have to be wrapped in a variant like type which contains the type value. e.g., struct Variant(T) { types type; T val; alias this = val; } which is a lightweight wrapper around anything. This is basically like std.variant.Variant except the type indicator comes from an enum. Again, this simplifies the discussion but it is not a problem for classes, structs, enums, or any other type, as long as they exist at compile time. I only used std.variant.Variant to simplify things, but the compiler would have to construct the typeid list internally. (I did it in my add explicitly for the types I was going to use) As far as runtime checking, no, because bits are bits. You can cast any pointer to any type you want and there is no way to know if it is suppose to be valid or not. This is why you have to include the type info somewhere for the object. classes have classinfo but there would be no way to validate it 100%.
Re: Container Array
On 09/07/2017 10:39 AM, Vino.B wrote: > Array!(Tuple!(string, ulong)) coSizeDirList () { You stated the return type explicitly above. > return tuple (dFiles[], Subdata[]); According to the error message, what is being returned does not have the same type: > Test1.d(27): Error: cannot implicitly convert expression > (tuple(dFiles.opSlice(), Subdata.opSlice())) of type > Tuple!(RangeT!(Array!(Tuple!string)), RangeT!(Array!ulong)) to > Array!(Tuple!(string, ulong)) The actual return type is Tuple!(RangeT!(Array!(Tuple!string)), RangeT!(Array!ulong)) There needs to be some transformations to match the two. Ali
Re: High-level wrapper for readline package
On Thursday, 7 September 2017 at 19:45:06 UTC, Adam D. Ruppe wrote: On Thursday, 7 September 2017 at 19:38:38 UTC, Nordlöw wrote: But I believe it's ok to relax it from `string` to `const(char)[]`, right? Yeah, it should be const(char)[] or even `in char[]` Ahh, correct.
Re: High-level wrapper for readline package
On Thursday, 7 September 2017 at 15:31:13 UTC, Nemanja Boric wrote: Minor point: you should add_history only if `lineStringz && lineStringz[0] != '\0'` Wonderful. That prevented a crashs when writing history. Thanks!
Re: High-level wrapper for readline package
On Thursday, 7 September 2017 at 19:38:38 UTC, Nordlöw wrote: But I believe it's ok to relax it from `string` to `const(char)[]`, right? Yeah, it should be const(char)[] or even `in char[]`
Re: High-level wrapper for readline package
On Thursday, 7 September 2017 at 16:23:46 UTC, Adam D. Ruppe wrote: On Thursday, 7 September 2017 at 16:18:09 UTC, bauss wrote: Isn't it pointless to make "prompt" in? No, it promises the function isn't doing anything weird to it (modify, which immutable covers, but also scope.. .unless dmd changed that), which means a copy of the pointer won't be stored either. Important to realize with C cuz then you know it is ok to use a temporary to it. But I believe it's ok to relax it from `string` to `const(char)[]`, right?
Re: New programming paradigm
On Thursday, 7 September 2017 at 17:13:43 UTC, EntangledQuanta wrote: On Thursday, 7 September 2017 at 15:36:47 UTC, Jesse Phillips wrote: [...] All types have a type ;) You specified in the above case that m is an int by setting it to 4(I assume that is what var(4) means). But the downside, at least on some level, all the usable types must be know or the switch cannot be generated(there is the default case which might be able to solve the unknown type problem in some way). [...] Nice for simple types but fail for struct, array & object Current variant implementation is lack of type-id to check for above ones. For this lacking, is there a runtime (not compile time - trait) to check if a type is a struct or array or object? Cheer
Re: Container Array
On Thursday, 7 September 2017 at 17:12:14 UTC, Vino.B wrote: On Thursday, 7 September 2017 at 15:07:56 UTC, Vino.B wrote: On Thursday, 7 September 2017 at 14:26:08 UTC, Ali Çehreli wrote: On 09/07/2017 03:56 AM, Vino.B wrote: writeln(coCleanFiles); Access the elements by taking a slice of the container: writeln(coCleanFiles[]); Ali Hi Ali, Thank you very much, was ablee to resolve this issue and now facing a new issue as the below code is not working as expected. The below code has to list the folders and their size's. import std.algorithm: filter, map, fold; import std.container; import std.file: SpanMode, dirEntries, isDir; import std.stdio: File, writefln, writeln; import std.typecons: tuple, Tuple; import std.parallelism: parallel; Array!(Tuple!(string, ulong)) coSizeDirList () { string FFs = "C:\\Temp\\TEST1\\BACKUP"; int SizeDir = 10; ulong subdirTotal; ulong subdirTotalGB; auto dFiles = Array!(Tuple!(string)) (dirEntries(FFs, SpanMode.shallow).filter!(a => a.isDir).map!(a => tuple(a.name))); foreach (d; dFiles) { auto SdFiles = Array!(Tuple!(ulong)) (dirEntries(d[0], SpanMode.depth).map!(a => tuple(a.size))); foreach(f; parallel(SdFiles, 1)) { subdirTotal += f.fold!((a, b) => a + b); } subdirTotalGB = (subdirTotal/1024/1024); if (subdirTotalGB > SizeDir) { auto Subdata = Array!(Tuple!(string, ulong))(dFiles ~ subdirTotalGB); } subdirTotal = 0; } return Subdata; } void main () { writeln (coSizeDirList[]); } Hi, Few updates, If i change the function to main i am able to print the required output, but if i change the main to function and call this function from another main then i am not able to return the result from the function. Updated Code: import std.algorithm: filter, map, fold; import std.container; import std.file: SpanMode, dirEntries, isDir; import std.stdio: File, writefln, writeln; import std.typecons: tuple, Tuple; import std.parallelism: parallel; import std.conv; Array!(Tuple!(string, ulong)) coSizeDirList () { //void main () { string FFs = "C:\\Temp\\sapnas2\\BACKUP"; int SizeDir = 1; ulong subdirTotal; ulong subdirTotalGB; Array!(Tuple!(ulong)) Subdata; auto dFiles = Array!(Tuple!(string)) (dirEntries(FFs, SpanMode.shallow).filter!(a => a.isDir).map!(a => tuple(a.name))); foreach (d; dFiles[]) { auto SdFiles = Array!(Tuple!(ulong)) (dirEntries(d[0], SpanMode.depth).map!(a => tuple(a.size))); foreach(f; SdFiles[]) { subdirTotal += f.fold!((a, b) => a + b); } subdirTotalGB = (subdirTotal/1024/1024); if (subdirTotalGB > SizeDir) { Subdata ~= subdirTotalGB; } subdirTotal = 0; } //writeln(dFiles); //writeln(Subdata); return dFiles[]; return Subdata[]; } void main () { writeln (coSizeDirList[]); } From, Vino.B Few Update: Update Code : import std.algorithm: filter, map, fold; import std.container; import std.file: SpanMode, dirEntries, isDir; import std.stdio: File, writefln, writeln; import std.typecons: tuple, Tuple; import std.parallelism: parallel; import std.conv; Array!(Tuple!(string, ulong)) coSizeDirList () { //void main () { string FFs = "C:\\Temp\\sapnas2\\BACKUP"; int SizeDir = 1; ulong subdirTotal; ulong subdirTotalGB; Array!ulong Subdata; auto dFiles = Array!(Tuple!(string)) (dirEntries(FFs, SpanMode.shallow).filter!(a => a.isDir).map!(a => tuple(a.name))); foreach (d; dFiles[]) { auto SdFiles = Array!(Tuple!(ulong)) (dirEntries(d[0], SpanMode.depth).map!(a => tuple(a.size))); foreach(f; SdFiles[]) { subdirTotal += f.fold!((a, b) => a + b); } subdirTotalGB = (subdirTotal/1024/1024); if (subdirTotalGB > SizeDir) { Subdata ~= subdirTotalGB; } subdirTotal = 0; } //writeln(dFiles[]); //writeln(Subdata[]); return tuple (dFiles[], Subdata[]); //return Subdata[]; //return Result; } void main () { writeln (coSizeDirList[]); } Error Output Test1.d(27): Error: cannot implicitly convert expression (tuple(dFiles.opSlice(), Subdata.opSlice())) of type Tuple!(RangeT!(Array!(Tuple!string)), RangeT!(Array!ulong)) to Array!(Tuple!(string, ulong)) Failed: ["dmd", "-v", "-o-", "Test1.d", "-I."] From, Vino.B
Re: One path skips constructor - is this a bug?
On Thursday, 7 September 2017 at 16:08:53 UTC, Piotr Mitana wrote: Code: === import std.conv; import std.regex; struct A This throws a compilation error: main.d(17): Error: one path skips constructor main.d(15): Error: return without calling constructor Why do I need the constructor call, if I throw the exception anyway? Is this a bug? This seems likely a bug, my understanding of this error is for class inheritance, where it must call the super constructor for all code paths to create the base class. With a struct the compiler always has the means to create the base and so it just seems to be be saying, "hey you called the constructor maybe you still want to do that here." And it would be a nice improvement to have control flow, but you may get away with it if you add assert(0); to the end of the constructor.
Re: New programming paradigm
On Thursday, 7 September 2017 at 15:36:47 UTC, Jesse Phillips wrote: On Monday, 4 September 2017 at 03:26:23 UTC, EntangledQuanta wrote: To get a feel for what this new way of dealing with dynamic types might look like: void foo(var y) { writeln(y); } var x = "3"; // or possibly var!(string, int) for the explicit types used foo(x); x = 3; foo(x); (just pseudo code, don't take the syntax literally, that is not what is important) While this example is trivial, the thing to note is that there is one foo declared, but two created at runtime. One for string and one for and int. It is like a variant, yet we don't have to do any testing. It is very similar to `dynamic` in C#, but better since actually can "know" the type at compile time, so to speak. It's not that we actually know, but that we write code as if we knew.. it's treated as if it's statically typed. It is an interesting thought but I'm not sure of its utility. First let me describe how I had to go about thinking of what this means. Today I think it would be possible for a given function 'call()' to write this: alias var = Algebraic!(double, string); void foo(var y) { mixin(call!writeln(y)); } Again the implementation of call() is yet to exist but likely uses many of the techniques you describe and use. Where I'm questioning the utility, and I haven't used C#'s dynamic much, is with the frequency I'm manipulating arbitrary data the same, that is to say: auto m = var(4); mixin(call!find(m, "hello")); This would have to throw a runtime exception, that is to say, in order to use the type value I need to know its type. All types have a type ;) You specified in the above case that m is an int by setting it to 4(I assume that is what var(4) means). But the downside, at least on some level, all the usable types must be know or the switch cannot be generated(there is the default case which might be able to solve the unknown type problem in some way). A couple of additional thoughts: The call() function could do something similar to pattern matching but args could be confusing: mixin(call!(find, round)(m, "hello")); But I feel that would just get confusing. The call() function could still be useful even when needing to check the type to know what operations to do. if(m.type == string) mixin(call!find(m, "hello")); instead of: if(m.type == string) m.get!string.find("hello"); The whole point is to avoid those checks as much as possible. With the typical library solution using variant, the checks are 100% necessary. With the solution I'm proposing, the compiler generates the checks behind the scenes and calls the template that corresponds to the check. This is the main difference. We can use a single template that the switch directs all checks to. But since the template is compile time, we only need one, and we can treat it like any other compile time template(that is the main key here, we are leveraging D's template's to deal with the runtime complexity). See my reply to Biotronic with the examples I gave as they should be more clear. The usefulness of such things are as useful as they are. Hard to tell without the actual ability to use them. The code I created in the other thread was useful to me as it allowed me to handle a variant type that was beyond my control(given to me by an external library) in a nice and simple way using a template. Since all the types were confluent(integral values), I could use a single template without any type dispatching... so it worked out well. e.g., Take com's variant. If you are doing com programming, you'll have to deal with it. The only way is a large switch statement. You can't get around that. Even with this method it will still require approximately the same checking because most of the types are not confluent. So, in these cases all the method does is push the "switch" in to the template. BUT it still turns it in to a compile time test(since the runtime test was done in the switch). Instead of one large switch one can do it in templates(and specialize where necessary) which, IMO, looks nicer with the added benefit of more control and more inline with how D works. Also, most of the work is simply at the "end" point. If, say, all of phobos was rewritten to us these variants instead of runtime types, then a normal program would have to deal very little with any type checking. The downside would be an explosion in size and decrease in performance(possibly mitigated to some degree but still large). So, it's not a panacea, but nothing is. I see it as more of a bridge between runtime and compile time that helps in certain cases quite well. e.g., Having to write a switch statement for all possible types a variable could have. With the mxin, or a comiler solution, this is reduced to virtually nothing in many cases and ends up just looking like normal D template code. Reme
Re: Container Array
On Thursday, 7 September 2017 at 15:07:56 UTC, Vino.B wrote: On Thursday, 7 September 2017 at 14:26:08 UTC, Ali Çehreli wrote: On 09/07/2017 03:56 AM, Vino.B wrote: writeln(coCleanFiles); Access the elements by taking a slice of the container: writeln(coCleanFiles[]); Ali Hi Ali, Thank you very much, was ablee to resolve this issue and now facing a new issue as the below code is not working as expected. The below code has to list the folders and their size's. import std.algorithm: filter, map, fold; import std.container; import std.file: SpanMode, dirEntries, isDir; import std.stdio: File, writefln, writeln; import std.typecons: tuple, Tuple; import std.parallelism: parallel; Array!(Tuple!(string, ulong)) coSizeDirList () { string FFs = "C:\\Temp\\TEST1\\BACKUP"; int SizeDir = 10; ulong subdirTotal; ulong subdirTotalGB; auto dFiles = Array!(Tuple!(string)) (dirEntries(FFs, SpanMode.shallow).filter!(a => a.isDir).map!(a => tuple(a.name))); foreach (d; dFiles) { auto SdFiles = Array!(Tuple!(ulong)) (dirEntries(d[0], SpanMode.depth).map!(a => tuple(a.size))); foreach(f; parallel(SdFiles, 1)) { subdirTotal += f.fold!((a, b) => a + b); } subdirTotalGB = (subdirTotal/1024/1024); if (subdirTotalGB > SizeDir) { auto Subdata = Array!(Tuple!(string, ulong))(dFiles ~ subdirTotalGB); } subdirTotal = 0; } return Subdata; } void main () { writeln (coSizeDirList[]); } Hi, Few updates, If i change the function to main i am able to print the required output, but if i change the main to function and call this function from another main then i am not able to return the result from the function. Updated Code: import std.algorithm: filter, map, fold; import std.container; import std.file: SpanMode, dirEntries, isDir; import std.stdio: File, writefln, writeln; import std.typecons: tuple, Tuple; import std.parallelism: parallel; import std.conv; Array!(Tuple!(string, ulong)) coSizeDirList () { //void main () { string FFs = "C:\\Temp\\sapnas2\\BACKUP"; int SizeDir = 1; ulong subdirTotal; ulong subdirTotalGB; Array!(Tuple!(ulong)) Subdata; auto dFiles = Array!(Tuple!(string)) (dirEntries(FFs, SpanMode.shallow).filter!(a => a.isDir).map!(a => tuple(a.name))); foreach (d; dFiles[]) { auto SdFiles = Array!(Tuple!(ulong)) (dirEntries(d[0], SpanMode.depth).map!(a => tuple(a.size))); foreach(f; SdFiles[]) { subdirTotal += f.fold!((a, b) => a + b); } subdirTotalGB = (subdirTotal/1024/1024); if (subdirTotalGB > SizeDir) { Subdata ~= subdirTotalGB; } subdirTotal = 0; } //writeln(dFiles); //writeln(Subdata); return dFiles[]; return Subdata[]; } void main () { writeln (coSizeDirList[]); } From, Vino.B
Re: New programming paradigm
On Thursday, 7 September 2017 at 14:28:14 UTC, Biotronic wrote: On Wednesday, 6 September 2017 at 23:20:41 UTC, EntangledQuanta wrote: So, no body thinks this is a useful idea or is it that no one understands what I'm talking about? Frankly, you'd written a lot of fairly dense code, so understanding exactly what it was doing took a while. So I sat down and rewrote it in what I'd consider more idiomatic D, partly to better understand what it was doing, partly to facilitate discussion of your ideas. The usage section of your code boils down to this: Sorry, I think you missed the point completely... or I didn't explain things very well. I see no where in your code where you have a variant like type. What I am talking about is quite simple: One chooses the correct template to use, not at compile time based on the type(like normal), but at runtime based on a runtime variable that specifies the type. This is has variants are normally used except one must manually call the correct function or code block based on the variable value. Here is a demonstration of the problem: import std.stdio, std.variant, std.conv; void foo(T)(T t) { writeln("\tfoo: Type = ", T.stringof, ", Value = ", t); } void bar(Variant val) { writeln("Variant's Type = ", to!string(val.type)); // foo called with val as a variant foo(val); writeln("Dynamic type conversion:"); switch(to!string(val.type)) { case "int": foo(val.get!int); break; // foo called with val's value as int case "float": foo(val.get!float); break; // foo called with val's value as float case "immutable(char)[]": foo(val.get!string); break; // foo called with val's value as string case "short": foo(val.get!short); break; // foo called with val's value as short default: writeln("Unknown Conversion!"); } } void main() { Variant val; writeln("\nVarant with int value:"); val = 3; bar(val); writeln("\n\nVarant with float value:"); val = 3.243f; bar(val); writeln("\n\nVarant with string value:"); val = "XXX"; bar(val); writeln("\n\nVarant with short value:"); val = cast(short)2; bar(val); getchar(); } Output: Varant with int value: Variant's Type = int foo: Type = VariantN!20u, Value = 3 Dynamic type conversion: foo: Type = int, Value = 3 Varant with float value: Variant's Type = float foo: Type = VariantN!20u, Value = 3.243 Dynamic type conversion: foo: Type = float, Value = 3.243 Varant with string value: Variant's Type = immutable(char)[] foo: Type = VariantN!20u, Value = XXX Dynamic type conversion: foo: Type = string, Value = XXX Varant with short value: Variant's Type = short foo: Type = VariantN!20u, Value = 2 Dynamic type conversion: foo: Type = short, Value = 2 The concept to gleam from this is that the switch calls foo with the correct type AT compile time. The switch creates the mapping from the runtime type that the variant can have to the compile time foo. So the first call to foo gives: `foo: Type = VariantN!20u, Value = 2`. The writeln call receives the val as a variant! It knows how to print a variant in this case, lucky for us, but we have called foo!(VariantN!20u)(val)! But the switch actually sets it up so it calls foo!(int)(val.get!int). This is a different foo! The switch statement can be seen as a dynamic dispatch that calls the appropriate compile time template BUT it actually depends on the runtime type of the variant! This magic links up a Variant, who's type is dynamic, with compile time templates. But you must realize the nature of the problem. Most code that uses a variant wouldn't use a single template to handle all the different cases: switch(to!string(val.type)) { case "int": fooInt(val.get!int); break; case "float": fooFloat(val.get!float); break; case "immutable(char)[]": fooString(val.get!string); break; case "short": fooShort(val.get!short); break; default: writeln("Unknown Conversion!"); } These functions might actually just be code blocks to handle the different cases. Now, if you understand that, the paradigm I am talking about is to have D basically generate all the switching code for us instead of us ever having to deal with the variant internals. We have something like void bar(var t) { writeln("\tbar: Type = ", t.type, ", Value = ", t); } AND it would effectively print the same results. var is akin to variant but the compiler understands this and generates N different bar's internally and a switch statement to dynamically call the desired one at runtime, yet, we can simply call bar with any value we want. e.g., void main() { bar(3); // calls bar as if bar was `vo
Re: SIMD under LDC
On Thursday, 7 September 2017 at 15:24:13 UTC, Johan Engelen wrote: On Wednesday, 6 September 2017 at 20:43:01 UTC, Igor wrote: I opened a feature request on github. I also tried using the gccbuiltins but I got this error: LLVM ERROR: Cannot select: 0x2199c96fd70: v16i8 = X86ISD::PSHUFB 0x2199c74e9a8, 0x2199c74d6c0 That's because SSSE3 instructions are not enabled by default, so the compiler isn't allowed to generate the PSHUFB instruction. Some options you have: 1. Set a cpu that has ssse3, e.g. compile with `-mcpu=native` 2. Enable SSSE3: compile with `-mattr=+ssse3` 3. Perhaps best for your case, enable SSSE3 for that function, importing the ldc.attributes module and using the @target("ssse3") UDA on that function. -Johan Thanks Johan. I tried this and now it does compile but it crashes with Access Violation in debug build. In optimized build it seems to be working though.
Re: High-level wrapper for readline package
On Thursday, 7 September 2017 at 16:18:09 UTC, bauss wrote: Isn't it pointless to make "prompt" in? No, it promises the function isn't doing anything weird to it (modify, which immutable covers, but also scope.. .unless dmd changed that), which means a copy of the pointer won't be stored either. Important to realize with C cuz then you know it is ok to use a temporary to it.
Re: High-level wrapper for readline package
On Thursday, 7 September 2017 at 14:00:36 UTC, Nordlöw wrote: On Thursday, 7 September 2017 at 13:44:52 UTC, Adam D. Ruppe wrote: [...] There's always room for usability improvements when wrapping C APIs... [...] Isn't it pointless to make "prompt" in?
One path skips constructor - is this a bug?
Code: === import std.conv; import std.regex; struct A { int field1; int field2; this(int field1, int field2) { if(field1 > field2) throw new Exception("This is illegal!"); } this(string str) { if(str.match(ctRegex!(`^[0-9]{4}-[0-9]{2}`))) this(str[0..4].to!int, str[5..7].to!int); else throw new Exception("Invalid string"); } } void main() { A(2004, 43); A("2004-43"); } === This throws a compilation error: main.d(17): Error: one path skips constructor main.d(15): Error: return without calling constructor Why do I need the constructor call, if I throw the exception anyway? Is this a bug?
Re: New programming paradigm
On Monday, 4 September 2017 at 03:26:23 UTC, EntangledQuanta wrote: To get a feel for what this new way of dealing with dynamic types might look like: void foo(var y) { writeln(y); } var x = "3"; // or possibly var!(string, int) for the explicit types used foo(x); x = 3; foo(x); (just pseudo code, don't take the syntax literally, that is not what is important) While this example is trivial, the thing to note is that there is one foo declared, but two created at runtime. One for string and one for and int. It is like a variant, yet we don't have to do any testing. It is very similar to `dynamic` in C#, but better since actually can "know" the type at compile time, so to speak. It's not that we actually know, but that we write code as if we knew.. it's treated as if it's statically typed. It is an interesting thought but I'm not sure of its utility. First let me describe how I had to go about thinking of what this means. Today I think it would be possible for a given function 'call()' to write this: alias var = Algebraic!(double, string); void foo(var y) { mixin(call!writeln(y)); } Again the implementation of call() is yet to exist but likely uses many of the techniques you describe and use. Where I'm questioning the utility, and I haven't used C#'s dynamic much, is with the frequency I'm manipulating arbitrary data the same, that is to say: auto m = var(4); mixin(call!find(m, "hello")); This would have to throw a runtime exception, that is to say, in order to use the type value I need to know its type. A couple of additional thoughts: The call() function could do something similar to pattern matching but args could be confusing: mixin(call!(find, round)(m, "hello")); But I feel that would just get confusing. The call() function could still be useful even when needing to check the type to know what operations to do. if(m.type == string) mixin(call!find(m, "hello")); instead of: if(m.type == string) m.get!string.find("hello");
Re: High-level wrapper for readline package
On Thursday, 7 September 2017 at 14:00:36 UTC, Nordlöw wrote: On Thursday, 7 September 2017 at 13:44:52 UTC, Adam D. Ruppe wrote: [...] There's always room for usability improvements when wrapping C APIs... [...] Minor point: you should add_history only if `lineStringz && lineStringz[0] != '\0'`
Re: SIMD under LDC
On Wednesday, 6 September 2017 at 20:43:01 UTC, Igor wrote: I opened a feature request on github. I also tried using the gccbuiltins but I got this error: LLVM ERROR: Cannot select: 0x2199c96fd70: v16i8 = X86ISD::PSHUFB 0x2199c74e9a8, 0x2199c74d6c0 That's because SSSE3 instructions are not enabled by default, so the compiler isn't allowed to generate the PSHUFB instruction. Some options you have: 1. Set a cpu that has ssse3, e.g. compile with `-mcpu=native` 2. Enable SSSE3: compile with `-mattr=+ssse3` 3. Perhaps best for your case, enable SSSE3 for that function, importing the ldc.attributes module and using the @target("ssse3") UDA on that function. -Johan
Re: Container Array
On Thursday, 7 September 2017 at 14:26:08 UTC, Ali Çehreli wrote: On 09/07/2017 03:56 AM, Vino.B wrote: writeln(coCleanFiles); Access the elements by taking a slice of the container: writeln(coCleanFiles[]); Ali Hi Ali, Thank you very much, was ablee to resolve this issue and now facing a new issue as the below code is not working as expected. The below code has to list the folders and their size's. import std.algorithm: filter, map, fold; import std.container; import std.file: SpanMode, dirEntries, isDir; import std.stdio: File, writefln, writeln; import std.typecons: tuple, Tuple; import std.parallelism: parallel; Array!(Tuple!(string, ulong)) coSizeDirList () { string FFs = "C:\\Temp\\TEST1\\BACKUP"; int SizeDir = 10; ulong subdirTotal; ulong subdirTotalGB; auto dFiles = Array!(Tuple!(string)) (dirEntries(FFs, SpanMode.shallow).filter!(a => a.isDir).map!(a => tuple(a.name))); foreach (d; dFiles) { auto SdFiles = Array!(Tuple!(ulong)) (dirEntries(d[0], SpanMode.depth).map!(a => tuple(a.size))); foreach(f; parallel(SdFiles, 1)) { subdirTotal += f.fold!((a, b) => a + b); } subdirTotalGB = (subdirTotal/1024/1024); if (subdirTotalGB > SizeDir) { auto Subdata = Array!(Tuple!(string, ulong))(dFiles ~ subdirTotalGB); } subdirTotal = 0; } return Subdata; } void main () { writeln (coSizeDirList[]); }
Re: Container Array
On 09/07/2017 03:56 AM, Vino.B wrote: writeln(coCleanFiles); Access the elements by taking a slice of the container: writeln(coCleanFiles[]); Ali
Re: New programming paradigm
On Wednesday, 6 September 2017 at 23:20:41 UTC, EntangledQuanta wrote: So, no body thinks this is a useful idea or is it that no one understands what I'm talking about? Frankly, you'd written a lot of fairly dense code, so understanding exactly what it was doing took a while. So I sat down and rewrote it in what I'd consider more idiomatic D, partly to better understand what it was doing, partly to facilitate discussion of your ideas. The usage section of your code boils down to this: alias EnumA = TypeMap!(float, int); alias EnumB = TypeMap!(double, byte); auto foo(T1, T2)(T1 a, T2 b) { import std.conv; return T1.stringof~": "~to!string(a)~" - "~T2.stringof~": "~to!string(b); } unittest { int a = 4; double b = 1.23; EnumA enumAVal = EnumA.get!float; EnumB enumBVal = EnumB.get!byte; auto res = enumMapper!(foo, enumAVal, enumBVal)(a, b); assert(res == "float: 4 - byte: 1"); } With this implementation behind the scenes: struct TypeMap(T...) { import std.meta : staticIndexOf; private int value; alias value this; alias Types = T; static TypeMap get(T2)() if (staticIndexOf!(T2, T) > -1) { return TypeMap(staticIndexOf!(T2, T)); } } template enumMapper(alias fn, Maps...) { auto enumMapper(Args...)(Args args) { return enumMapperImpl!(OpaqueAliasSeq!(), Args)(args); } auto enumMapperImpl(alias ArgTypes, Args...)(Args args) { alias Assigned = ArgTypes.Aliases; alias Remaining = Maps[Assigned.length..$]; static if (Remaining.length == 0) { import std.traits : Parameters; alias fun = fn!Assigned; alias params = Parameters!fun; return fun(castTuple!params(args).expand); } else { alias typemap = Remaining[0]; switch (typemap) { foreach (T; typemap.Types) { case typemap.get!T: alias Types = OpaqueAliasSeq!(Assigned, T); return enumMapperImpl!Types(args); } default: assert(false); } } } } template castTuple(T...) { import std.typecons : tuple; auto castTuple(Args...)(Args args) if (Args.length == T.length) { static if (T.length == 0) { return tuple(); } else { auto result = .castTuple!(T[1..$])(args[1..$]); return tuple(cast(T[0])args[0], result.expand); } } } template OpaqueAliasSeq(T...) { alias Aliases = T; }
Re: High-level wrapper for readline package
On Thursday, 7 September 2017 at 13:44:52 UTC, Adam D. Ruppe wrote: On Thursday, 7 September 2017 at 13:37:16 UTC, Nordlöw wrote: Have anybody cooked together high-level bindings on top of the C-bindings for libreadline here Have you ever used readline? The basic C api is already very high level: char* from_user = readline("Prompt> "); I don't think there's a lot to gain by wrapping that... There's always room for usability improvements when wrapping C APIs... Here's what I hacked together: version = readline; extern(C) void add_history(const char*); // missing from gnu.readline /** High-level wrapper around GNU libreadline. */ const(char)[] readLine(in string prompt, bool useHistory = true) { version(readline) { import gnu.readline : readline; import std.string : toStringz, fromStringz; const lineStringz = readline(prompt.toStringz); if (useHistory) { add_history(lineStringz); } return lineStringz.fromStringz; } else { write(prompt); stdout.flush; return readln.strip; } }
Re: High-level wrapper for readline package
On Thursday, 7 September 2017 at 13:37:16 UTC, Nordlöw wrote: Have anybody cooked together high-level bindings on top of the C-bindings for libreadline here Have you ever used readline? The basic C api is already very high level: char* from_user = readline("Prompt> "); I don't think there's a lot to gain by wrapping that...
High-level wrapper for readline package
Have anybody cooked together high-level bindings on top of the C-bindings for libreadline here http://code.dlang.org/packages/readline ?
Re: DLang IDE [RU]
On Thursday, 7 September 2017 at 07:03:41 UTC, Vadim Lopatin wrote: On Wednesday, 6 September 2017 at 17:36:53 UTC, TM wrote: On Wednesday, 6 September 2017 at 14:33:18 UTC, Vadim Lopatin wrote: On Wednesday, 6 September 2017 at 14:06:56 UTC, TM wrote: On Wednesday, 6 September 2017 at 13:07:04 UTC, Vadim Lopatin wrote: File / new для добавления пакетов/модулей не пойдет? Удалять также можно. Перемещать - нельзя. File / new создает модуль. А как создавать пакет? New Source File -> Location -> Bew Folder ? Удалять возможности не нашел Удобного создания package нет, можно использовать workaround: Да тут ключевое слово "удобный", пока удобней создавать через сторонний файловый менеджер. В Netbeans в его аналоге "Workspace Explorer" правый клик и в контекстном меню на выбор Новый -> Папка, класс, пакет, интерфейс и т.д. Хорошо, если бы чтото подобное было реализовано в Dlang IDE. Новый класс/енум/интерфейс имеет смысл для java, где, как правило, один класс = один файл. Для D самая полезная функция - создать модуль. Если при открытии диалога создать файл будет выбран шаблон модуль и фокус на редакторе имени, а по Enter - срабатывать кнопка создания файла - все будет удобно. Это понятно, что у Java своя организационная специфика, в принципе если в диалоге создание файла минимизировать количество кликов, то есть сразу вводишь имя файла с клавиатуры и кнопка создания будет реагировать на Entrer (а не Ctrl+N), будет вполне юзабельно.
Re: Container Array
On Wednesday, 6 September 2017 at 16:41:06 UTC, Vino.B wrote: HI All, Can some one provide me a example of how to use the std.container.array for the below code. import std.algorithm: filter, map; import std.file: SpanMode, dirEntries, isDir; import std.stdio: writeln; import std.typecons: tuple; import std.array: array; void main () { string[] Filesys = ["C:\\Temp\\TEST1\\BACKUP", "C:\\Temp\\TEST2\\EXPORT"]; foreach(FFs; Filesys) { auto dFiles = dirEntries("C:\\Temp\\TEST1\\BACKUP", SpanMode.shallow).filter!(a => a.isDir).map!(a => tuple(a.name, a.size)); foreach(d; dFiles) writeln(d[0], "\t", d[1]); } } From, Vino.B Hi, I tried a small code using container array, and the output i get form the code is a below, so can one help me on this issue. Program: import std.algorithm: filter, map; import std.file: SpanMode, dirEntries, isDir; import std.stdio: writeln; import std.typecons: tuple, Tuple; import std.container; Array!(Tuple!(string, string)) coCleanFiles() { auto dFiles = make!Array(dirEntries("C:\\Temp\\TEST1\\BACKUP", SpanMode.shallow).filter!(a => a.isFile).map!(a => tuple(a.name, a.timeCreated.toSimpleString[0 .. 20]))); return dFiles; } void main () { writeln(coCleanFiles); } Output: Array!(Tuple!(string, string))(RefCounted!(Payload, cast(RefCountedAutoInitialize)0)(RefCountedStore(62D818))) From, Vino.B
Re: New programming paradigm
On Wednesday, 6 September 2017 at 23:20:41 UTC, EntangledQuanta wrote: So, no body thinks this is a useful idea or is it that no one understands what I'm talking about? I think it may be a good use, although I haven't invested so much time looking into your particular application. It looks like a normal, sane use of templates. This is what they are primarily intended for. And yes, combining them with mixins provide some great possibilities that are not available in many other languages. Have you seen how D recommends avoiding duplicate code when overloading operators, also by means of mixins: https://dlang.org/spec/operatoroverloading.html#binary I thought you may come from C since you mention void pointers as an alternative. But that is not considered the normal way in D, your new way is far better, and more "normal". It looks you may be mistaking what happens at "run-time", or it may be a way of speaking. In D, templates called with different types generate different code already at compile-time -- even if in the source code you write, it all looks and works so polymorphically. This is a similar approach as in C++ and it's why D generics are called "templates"; as opposed for example to C#, where generics are not compiled into static types and keep existing at run-time. Andrei discusses both approaches in his book, and why the first one was chosen for D.
Re: DLang IDE [RU]
On Wednesday, 6 September 2017 at 13:05:29 UTC, Vadim Lopatin wrote: On Tuesday, 5 September 2017 at 15:40:06 UTC, TM wrote: 1. Добавить возможность выбора размера шрифта для области редактирования. Я крайне редко меняю подобные настройки в IDE, но в данном случае дефолтный шрифт оказался откровенно мелковат (возможно под Linux ситуация несколько иная), пришлось за не имением выбора размера шрифта искать более крупный шрифт. Submitted issue / feature request: Add editors default font size setting https://github.com/buggins/dlangide/issues/249 Implemented in v0.7.68 Win32 binaries are released.
Re: DLang IDE [RU]
On Wednesday, 6 September 2017 at 13:20:08 UTC, Vadim Lopatin wrote: On Tuesday, 5 September 2017 at 15:40:06 UTC, TM wrote: 2. В области Workspace Explorer на одном уровне иерархии модули и пакеты сортируются по алфавиту, но "вперемешку" с друг другом, в отличие от того же Notepad++, где сначала по алфавиту сортируются пакеты, а потом модули. Понимая, что такой режим также может оказаться неудобным для части пользователей, предлагаю сделать настройку с режимом сортировки. И если, файлы package.d имеют некий "особый" статус в языке, возможно имеет смысл выделять их как-то (например другой иконкой или font.bold=true) Надо исправлять, просто не замечал. Issue submitted: https://github.com/buggins/dlangide/issues/250 Fixed in v0.7.67
Re: DLang IDE [RU]
On Thursday, 7 September 2017 at 07:04:11 UTC, Suliman wrote: А можно сделать как-то так, чтобы автокомплит работал сразу? Как в студии. То есть бы не приходилось ctrl+пробел нажимать. Issue submitted: https://github.com/buggins/dlangide/issues/253
Re: DLang IDE [RU]
А можно сделать как-то так, чтобы автокомплит работал сразу? Как в студии. То есть бы не приходилось ctrl+пробел нажимать.
Re: DLang IDE [RU]
On Wednesday, 6 September 2017 at 17:36:53 UTC, TM wrote: On Wednesday, 6 September 2017 at 14:33:18 UTC, Vadim Lopatin wrote: On Wednesday, 6 September 2017 at 14:06:56 UTC, TM wrote: On Wednesday, 6 September 2017 at 13:07:04 UTC, Vadim Lopatin wrote: File / new для добавления пакетов/модулей не пойдет? Удалять также можно. Перемещать - нельзя. File / new создает модуль. А как создавать пакет? New Source File -> Location -> Bew Folder ? Удалять возможности не нашел Удобного создания package нет, можно использовать workaround: Да тут ключевое слово "удобный", пока удобней создавать через сторонний файловый менеджер. В Netbeans в его аналоге "Workspace Explorer" правый клик и в контекстном меню на выбор Новый -> Папка, класс, пакет, интерфейс и т.д. Хорошо, если бы чтото подобное было реализовано в Dlang IDE. Новый класс/енум/интерфейс имеет смысл для java, где, как правило, один класс = один файл. Для D самая полезная функция - создать модуль. Если при открытии диалога создать файл будет выбран шаблон модуль и фокус на редакторе имени, а по Enter - срабатывать кнопка создания файла - все будет удобно. Создание папок само по себе достаточно бесполезно. Папки без файлов не показываются в Workspace explorer, а новая папка с файлом создается в диалоге выбора папки для файла. В Workspace Explorer есть еще один если не баг, то не очень удобный момент: при закрытии вкладки с кодом или при создании нового модуля, то есть по сути при "рефреше" дерева слетает текущее позиционирование курсора и состояние закрытых открытых узлов дерева. То есть перед "рефрешем" надо сохранить состояние курсора и состояние узлов дерева(раскрыт/закрыт), а после обновления восстановить (по-возможности) как было, с учетом того, что какие-то файлы/папки могут быть удалены. Я подобное реализовывал даже на допотопном Treeview ActiveX от майкрософта, тут же имея свой "карманный" GUI как говорится все карты в руки это допилить. Issue submitted: https://github.com/buggins/dlangide/issues/252