Re: Natural sorted list of files
On Wednesday, 8 February 2017 at 07:41:29 UTC, Ali Çehreli wrote: test.naturalSort would sort the array in place before calling writeln and 'test' would appear naturally sorted as well. I've fixed it like this: Great! Thank you!
Re: Natural sorted list of files
On 02/06/2017 09:00 PM, Dmitry wrote: > On Monday, 6 February 2017 at 18:57:17 UTC, Ali Çehreli wrote: >> I think it's now std.algorithm.chunkBy. Please fix Rosetta > > Thank you! > I fixed Thank you! > but anyway it works incorrect (it doesn't any changes): The problem was with the following loop: foreach (test; tests) writeln(test, "\n", test.naturalSort, "\n"); test.naturalSort would sort the array in place before calling writeln and 'test' would appear naturally sorted as well. I've fixed it like this: foreach (test; tests) { printTexts("Test strings", test); printTexts("Normally sorted", test.dup.sort()); printTexts("Naturally sorted", test.dup.naturalSort()); } I had fun inserting "[sic]"s both in source code and in the output for the INDEPENENT typo in the problem description. :D void printTexts(Range)(string tag, Range range) { const sic = range.front.canFind("INDEPENENT") ? " [sic]" : ""; writefln("\n%s%s:\n%-( |%s|%|\n%)", tag, sic, range); } I also made the output more readable: Test strings: |ignore leading spaces: 2-2| | ignore leading spaces: 2-1| | ignore leading spaces: 2+1| | ignore leading spaces: 2+0| Normally sorted: | ignore leading spaces: 2+1| | ignore leading spaces: 2+0| | ignore leading spaces: 2-1| |ignore leading spaces: 2-2| Naturally sorted: | ignore leading spaces: 2+0| | ignore leading spaces: 2+1| | ignore leading spaces: 2-1| |ignore leading spaces: 2-2| [...] Ali
Re: Pass type directly to a template function?
On 02/07/2017 01:17 AM, Chris Katko wrote: void function3(T)(T) //hypothetical, specify the datatype in the argument list { T data; } Related: https://dlang.org/library/object/type_info.html and https://dlang.org/library/object/object.factory.html This compiles but I'm not sure how to use it effectively: import std.stdio; auto function3(TypeInfo ti) { return ti.initializer(); } void main() { writeln(function3(typeid(float))); writeln(function3(typeid(double))); } Ali
Re: Pass type directly to a template function?
On Tuesday, 7 February 2017 at 21:40:04 UTC, Dukc wrote: On Tuesday, 7 February 2017 at 10:21:20 UTC, Mike Parker wrote: function2!float(); //? function3!float(); //? Yes, this is how it's done. Not quite with function3, because it takes one unnamed runtime parameter. It can be called like function1 however. The value of the parameter does not matter because it's unused, only the type. Yes, I missed the runtime parameter.
Re: Array start index
On 02/07/2017 02:04 PM, Bastiaan Veelo wrote: >> This optimization cannot work if the array is a static array inside >> the same struct. It would work with a dynamic array but then it would >> probably be slower than applying the *(ptr+index) technique. > > You mean slower than the _payload[index - first] technique? Is that > because of heap memory versus stack memory? Mandatory disclaimer: We can't be sure without testing. Not exactly because stack versus heap because the whole object might be sitting in heap memory anyway: alias S = StaticArray!(/* ... */); S[] objects; objects ~= S(/* ... */); So, all of those are on the heap. It's more about having everything at hand, near each other, close in memory. If the member is a static array, then when we have an S[], all members are there to be operated on. If the array in dynamic, then an S[] has indirections, reaching out to the heap, which may involve long-latency memory reads. foreach (s; objects) { s[42];// May have a cache miss and read from memory } In the static array case, the entire body of s is already on the cache. On the other hand, when the objects are large, then few of those can fit in the cache. etc. One needs to profile to see what works better. > Am I correct that the reason that a dynamic array would work is because > it is allocated independently from the struct, meaning that its address > stays the same even if the struct is moved? Yes, that would be a requirement to prevent the self-reference. > We could .reserve a dynamic > array in initialize() to prevent it being resized. Makes sense. Another solution that came to my mind: You can keep the self-referencing solution but make sure that the objects are not moved after initialize(): S[] objects; objects.reserve(100); objects.each!(o => o.initialize()); // The objects will not move if you're careful > Thanks again. > Bastiaan. Ali
Re: Array start index
On Tuesday, 7 February 2017 at 20:33:35 UTC, Ali Çehreli wrote: On 02/07/2017 02:11 AM, Bastiaan Veelo wrote: > We do not need to take measures against the GC? Of course we have to and the struct that I wrote is illegal because it is self-referencing through the _ptr member. (D has the right to move structs around, making my _ptr potentially pointing to an illegal address.) Gosh am I glad I brought that up, and for people like you hanging out in the learn group. Thanks for pointing this out! This optimization cannot work if the array is a static array inside the same struct. It would work with a dynamic array but then it would probably be slower than applying the *(ptr+index) technique. You mean slower than the _payload[index - first] technique? Is that because of heap memory versus stack memory? Am I correct that the reason that a dynamic array would work is because it is allocated independently from the struct, meaning that its address stays the same even if the struct is moved? We could .reserve a dynamic array in initialize() to prevent it being resized. Thanks again. Bastiaan.
Re: Why File.rawRead is @system?
On Tuesday, 7 February 2017 at 09:21:18 UTC, Kagamin wrote: Can't find a reason why it's not inferred @safe (on linux). Any idea? Perhaps you are trying to read as a type for which a conversion from string to it is @system? Not sure if that's possible.
Re: Pass type directly to a template function?
On Tuesday, 7 February 2017 at 10:21:20 UTC, Mike Parker wrote: function2!float(); //? function3!float(); //? Yes, this is how it's done. Not quite with function3, because it takes one unnamed runtime parameter. It can be called like function1 however. The value of the parameter does not matter because it's unused, only the type.
Re: Array start index
On Tuesday, 7 February 2017 at 20:28:30 UTC, Ali Çehreli wrote: You forgot to call that most important function. ;) Hah of course. I assumed the name would give it some special meaning, like postblit. 1) I don't understand the first assert there, which does not pass for me, so I commented it out. The intention is to check that (_payload.ptr - first) is larger than 0. 2) May bad: init() is not a good name for a struct member, so it should be renamed: void initialize() { // assert( first < cast(size_t)_payload.ptr); // Address space underrun. assert(-first < size_t.max - cast(size_t)_payload.ptr); // Address space overrun. this._ptr = _payload.ptr - first; } 3) Instead of having to remember to call it, let's introduce a function that does it for us: auto makeStaticArray(T, ptrdiff_t first, ptrdiff_t last)() { auto s = StaticArray!(T, first, last)(); s.initialize(); return s; } OK good. unittest { // StaticArray!(int, -10, 10) arr; auto arr = makeStaticArray!(int, -10, 10); > foreach (i, ref e; arr) > e = i; Unrelated: That line passes because you're building 32-bits. Here is the error I got: Error: cannot implicitly convert expression (i) of type long to int You can cast it: e = cast(int)i; or by import std.conv : to; e = i.to!int; Thanks a lot for your illustrative answers, including the next one! Bastiaan.
Re: Array start index
Pressed send too soon, before considering your GC question. On 02/07/2017 02:11 AM, Bastiaan Veelo wrote: > We do not need to take measures against the GC? Of course we have to and the struct that I wrote is illegal because it is self-referencing through the _ptr member. (D has the right to move structs around, making my _ptr potentially pointing to an illegal address.) This optimization cannot work if the array is a static array inside the same struct. It would work with a dynamic array but then it would probably be slower than applying the *(ptr+index) technique. Ali
Re: Array start index
On 02/07/2017 02:11 AM, Bastiaan Veelo wrote: > void init() { > assert( first < cast(size_t)_payload.ptr); // > Address space underrun. > assert(-first < size_t.max - cast(size_t)_payload.ptr); // > Address space overrun. > this._ptr = _payload.ptr - first; > } You forgot to call that most important function. ;) 1) I don't understand the first assert there, which does not pass for me, so I commented it out. 2) May bad: init() is not a good name for a struct member, so it should be renamed: void initialize() { // assert( first < cast(size_t)_payload.ptr); // Address space underrun. assert(-first < size_t.max - cast(size_t)_payload.ptr); // Address space overrun. this._ptr = _payload.ptr - first; } 3) Instead of having to remember to call it, let's introduce a function that does it for us: auto makeStaticArray(T, ptrdiff_t first, ptrdiff_t last)() { auto s = StaticArray!(T, first, last)(); s.initialize(); return s; } unittest { // StaticArray!(int, -10, 10) arr; auto arr = makeStaticArray!(int, -10, 10); > foreach (i, ref e; arr) > e = i; Unrelated: That line passes because you're building 32-bits. Here is the error I got: Error: cannot implicitly convert expression (i) of type long to int You can cast it: e = cast(int)i; or by import std.conv : to; e = i.to!int; Ali
Re: Initialization of dynamic multidimensional array
auto arr = uninitializedArray!(int[][])(ROWS,COLS); arr.each!"a[]=-1"; This looks like what I was looking for. At least I think I understand what's going on here. The other two suggestions are beyond my scope yet, but I'll come back, when I improved on my D skills. Thanks for your replies.
Re: Initialization of dynamic multidimensional array
On Sunday, 5 February 2017 at 20:33:06 UTC, berni wrote: With X not known at compile time: auto arr = new int[][](X,X); for (int i=0;i
Re: How do I call a C++ struct default constructor from D?
On Tuesday, 7 February 2017 at 13:37:01 UTC, Atila Neves wrote: Here still example https://pp.vk.me/c636630/v636630885/46579/neSdIip1ySI.jpg
Re: How do I call a C++ struct default constructor from D?
On Tuesday, 7 February 2017 at 13:37:01 UTC, Atila Neves wrote: On Tuesday, 7 February 2017 at 10:46:24 UTC, kinke wrote: I've only every done trivial C++ integration before. As soon as I tried something "real" it all broke down incredibly fast. Probably going to have to file some bugs on name mangling. Atila Perhaps this video will help https://www.youtube.com/watch?v=HTgJaRRfLPk
Re: How do I call a C++ struct default constructor from D?
On Tuesday, 7 February 2017 at 10:46:24 UTC, kinke wrote: On Tuesday, 7 February 2017 at 10:15:09 UTC, Atila Neves wrote: I can declare a C++ struct like so: extern(C++, mynamespace) struct Foo { //... } But... I don't want to repeat the initialisation code for that struct's default constructor. I can't declare one in D because D doesn't allow default constructors for structs. What's my way out? Thanks, Atila I'm afraid there's no way out. I summarized some of my C++ interop findings incl. default constructor here: http://forum.dlang.org/thread/nqxsdehlydizatopr...@forum.dlang.org Ugh, I was afraid of that. I ended up having to write (!) a C++ function that returned the default-initialised struct and called that from D. It got uglier soon after... I've only every done trivial C++ integration before. As soon as I tried something "real" it all broke down incredibly fast. Probably going to have to file some bugs on name mangling. Atila
Re: How do I call a C++ struct default constructor from D?
On Tuesday, 7 February 2017 at 10:15:09 UTC, Atila Neves wrote: I can declare a C++ struct like so: extern(C++, mynamespace) struct Foo { //... } But... I don't want to repeat the initialisation code for that struct's default constructor. I can't declare one in D because D doesn't allow default constructors for structs. What's my way out? Thanks, Atila I'm afraid there's no way out. I summarized some of my C++ interop findings incl. default constructor here: http://forum.dlang.org/thread/nqxsdehlydizatopr...@forum.dlang.org
Re: Pass type directly to a template function?
On Tuesday, 7 February 2017 at 09:17:04 UTC, Chris Katko wrote: Can I pass a type, instead of a variable of a type, to a template function in order to decide the datatype of T in a function? Yes. That's rather the point. function1(f); //works That is actually shorthand for this: function1!float(f); The compiler is inferring the type of f for you. function2!float(); //? function3!float(); //? Yes, this is how it's done. function3(float); //? function3(double); //? No. This won't compile. It seems like this would be a useful construct for Factory pattern that assembles any class that you specify as long as the called methods work out. (ala Duck Typing, "if it walks() and quacks() like a duck, it's a duck") The range infrastructure is based on this concept.
How do I call a C++ struct default constructor from D?
I can declare a C++ struct like so: extern(C++, mynamespace) struct Foo { //... } But... I don't want to repeat the initialisation code for that struct's default constructor. I can't declare one in D because D doesn't allow default constructors for structs. What's my way out? Thanks, Atila
Re: Array start index
On Monday, 6 February 2017 at 23:42:55 UTC, Ali Çehreli wrote: Then you use _ptr when indexing: // Support e = arr[5]; ref T opIndex(ptrdiff_t index) { assert(index >= first); assert(index <= last); return *(_ptr + index); } Ali Thank you very much for your time. Sadly this gives me an access violation. The traceback doesn't seem right though, as it seems to jump to opIndexAssign from where opIndex is used. If I'm not mistaken, I have confirmed that _ptr is a valid address, see below. We do not need to take measures against the GC? - Bastiaan. On Windows: rdmd -main -unittest -debug -g source\epcompat\array.d object.Error@(0): Access Violation 0x00402057 in void epcompat.array.__unittestL81_1() at C:\SARC\Pascal2017\D\epcompat\source\epcompat\array.d(88) 0x0040465C in void epcompat.array.__modtest() at C:\SARC\Pascal2017\D\epcompat\source\epcompat\array.d(39) 0x0040A455 in int core.runtime.runModuleUnitTests().__foreachbody1(object.ModuleInfo*) 0x0040C007 in int object.ModuleInfo.opApply(scope int delegate(object.ModuleInfo*)).__lambda2(immutable(object.ModuleInfo*)) 0x00406808 in _d_run_main 0x004046D4 in main at C:\SARC\Pascal2017\D\epcompat\source\epcompat\array.d(7) 0x004225DD in mainCRTStartup 0x779C62C4 in BaseThreadInitThunk 0x77B50FD9 in RtlSubscribeWnfStateChangeNotification 0x77B50FA4 in RtlSubscribeWnfStateChangeNotification The complete source: module epcompat.array; // Test with rdmd -main -unittest -debug -g source\epcompat\array.d alias StaticArray_offset StaticArray; /* * A fixed-length array with an index that runs from $(D_PARAM first) * to $(D_PARAM last) inclusive. * * Implemented by means of an offset pointer. */ struct StaticArray_offset(T, ptrdiff_t first, ptrdiff_t last) { T[last - first + 1] _payload; T* _ptr; void init() { assert( first < cast(size_t)_payload.ptr); // Address space underrun. assert(-first < size_t.max - cast(size_t)_payload.ptr); // Address space overrun. this._ptr = _payload.ptr - first; } size_t length() { return _payload.length; } // Support e = arr[5]; ref T opIndex(ptrdiff_t index) { assert(index >= first); assert(index <= last); return *(_ptr + index); } // Support arr[5] = e; void opIndexAssign(U : T)(auto ref U value, ptrdiff_t index) { assert(index >= first); assert(index <= last); *(_ptr + index) = value; } // Line 39 // Support foreach(e; arr). int opApply(scope int delegate(ref T) dg) { int result = 0; for (int i = 0; i < _payload.length; i++) { result = dg(_payload[i]); if (result) break; } return result; } // Support foreach(i, e; arr). int opApply(scope int delegate(ptrdiff_t index, ref T) dg) { int result = 0; for (int i = first; i <= last; i++) { result = dg(i, *(_ptr + i)); if (result) break; } return result; } // Write to binary file. void toFile(string fileName) { import std.stdio; auto f = File(fileName, "wb"); if (f.tryLock) { f.rawWrite(_payload); } } } unittest { StaticArray!(int, -10, 10) arr; assert(arr.length == 21); foreach (ref e; arr) e = 42; assert(arr[-10] == 42); // Line 88 assert(arr[0] == 42); assert(arr[10] == 42); foreach (i, ref e; arr) e = i; assert(arr[-10] == -10); assert(arr[0] == 0); assert(arr[5] == 5); assert(arr[10] == 10); arr[5] = 15; assert(arr[5] == 15); }
Re: Why File.rawRead is @system?
On Tuesday, 7 February 2017 at 09:21:18 UTC, Kagamin wrote: Can't find a reason why it's not inferred @safe (on linux). Any idea? Uh ? It's safe Just tried import std.stdio; void main(string[] args) @safe { File f; ubyte[] z; z = f.rawRead(z); } And it compiles (DMD 2.073, Linux, X86_64)
Why File.rawRead is @system?
Can't find a reason why it's not inferred @safe (on linux). Any idea?
Pass type directly to a template function?
Can I pass a type, instead of a variable of a type, to a template function in order to decide the datatype of T in a function? void function(T)(T x) //works { T data; //do stuff with T, ignoring x. } void function2(T)() //hypothetical, specify the type... somehow? { T data; } void function3(T)(T) //hypothetical, specify the datatype in the argument list { T data; } void main() { float f=0; float d=0; function1(f); //works function1(d); //works function2!float(); //? function3!float(); //? function3(float); //? function3(double); //? } It seems like this would be a useful construct for Factory pattern that assembles any class that you specify as long as the called methods work out. (ala Duck Typing, "if it walks() and quacks() like a duck, it's a duck")