Re: Template pattern delegate?
On Sunday, 25 October 2020 at 12:02:10 UTC, Ali Çehreli wrote: On 10/25/20 4:30 AM, frame wrote: Is there a possibility to write templated code / custom trait pattern with usage like a delegate? I have a try-catch block with different types and don't want to repeat myself in every method again. It's always the same, just what's tried changes, eg.: pseudo code: template myStuff(mixin code) { try { code(); } catch (X e) { ... } catch (Y e) { ... } ... } static myStuff!({ writeln("..."); }); That's one of my DConf Onlide slides but for a limited use case! :) int tried(Func, string functionName = __FUNCTION__, string file = __FILE__, size_t line = __LINE__)(Func func) { static if (!is (ReturnType!Func == int)) { pragma(msg, format!"\n%s(%s): Error: %s must return int error code"(file, line, functionName)); static assert(false); } void printError(T)(T err) { stderr.writefln!"\n%s(%s): Failed to execute %s: %s"(file, line, functionName, err); } try { return func(); } catch (Exception exc) { printError(exc.msg); return 1; } catch (Error err) { printError(err); import core.stdc.stdlib : abort; abort(); } assert(false); } Then, all extern(C) functions would be written the same way: extern(C) int foo() { return tried({ // ... return 0; }); } Ali I see that your approach can handle functions and delegates but isn't that not equivalent like this template for a function? auto myStuff(T)(T function() fn) { try { return fn(); } catch (Exception e) { // } } I wonder if I could use such a template as static variant and the compiler just expands the code? Just thinking that using a function or delegate is an overhead. Maybe not a function but a delegate will allocate GC memory I think.
Re: Unexpected behaviour using remove on char[]
On 10/25/20 12:29 PM, IGotD- wrote: What I discovered is that remove doesn't really remove size number of bytes but also removed entire multibyte characters and consider that one step. The result was of course that I got out of bounds exceptions as it went past the end. This is the infamous "auto decode" at work. When I changed char[] to ubyte[] my code started to work correctly again. Instead of changing the type, you can temporarily treat them as ubyte[] with std.string.representation: import std.stdio; import std.string; void print(R)(R range) { writefln!"%-(%s, %)"(range); } void main() { auto s = "abcçd".dup; print(s); print(s.representation); } Prints: a, b, c, ç, d 97, 98, 99, 195, 167, 100 Ali
Unexpected behaviour using remove on char[]
I have a part in my code that use remove buffer.remove(tuple(0, size)); with char[] buffer What I discovered is that remove doesn't really remove size number of bytes but also removed entire multibyte characters and consider that one step. The result was of course that I got out of bounds exceptions as it went past the end. When I changed char[] to ubyte[] my code started to work correctly again. According to the documentation a char is an "unsigned 8 bit (UTF-8 code unit)" so you really believe you are working on bytes. I presume that under the hood there are range iterators at work and those work multibyte characters. However you can iterate over one byte characters as well as an option and you don't know what happens underneath. I'm a bit confused, when should I expect that the primitives work with single versus multibyte chars in array operations?
Re: Can we do compile time reading part of a file using import?
On Friday, 23 October 2020 at 16:42:00 UTC, data pulverizer wrote: Hi all, the `import` function allows a file to be read at compile time, which opens up great opportunities for (mostly binary) file IO, where data types can be coded into files - the user doesn't need to know data types ahead of time. As specified in my old blog article: https://www.active-analytics.com/blog/reading-idx-files-in-d/. Binary files can be very large and reading the whole file at compile time is often unnecessary. This isn't exactly the intended use for the function, but there it is. Since compile time read capability already exists and is useful, adding capability to be able to read only a portion of the file at compile time in a given location is advantageous and has utility. For me it's not make-or-break, it just something very useful and I think has clear use case. Please let me know if there are aspects or alternatives I am missing. Thanks That's a really good approach, I always wanted to do things like this in C# but that wasn't possible due to C#'s lack of CTFE. Could be good if we find a out a way to read part of the file and lazy-reading.Sure an external tool could do the first job, I mean if we could find a way in pure D.
Re: Can we do compile time reading part of a file using import?
On Sunday, 25 October 2020 at 12:16:36 UTC, Jacob Carlborg wrote: On 2020-10-23 18:42, data pulverizer wrote: For me it's not make-or-break, it just something very useful and I think has clear use case. Please let me know if there are aspects or alternatives I am missing. You could always have the build tool split up the file in multiple smaller files and read one of the smaller files with the import expression. Which build tool are you refering to? an existing one or build one oneself to do this job?
Re: Can we do compile time reading part of a file using import?
On Sunday, 25 October 2020 at 12:16:36 UTC, Jacob Carlborg wrote: On 2020-10-23 18:42, data pulverizer wrote: You could always have the build tool split up the file in multiple smaller files and read one of the smaller files with the import expression. Thanks. My current solution is to have a metadata file where all the type information is stored and then the data file separately. I should have been clearer when I asked if there was something I was missing, like whether there is another way to do compile time read without reading the whole file. I think the feature I suggested is a useful one to bear in mind for future versions of D. It would save on preprocessing large files before reading them. I don't know how `import` for file reads works at the moment, and correct me if I'm wrong but it doesn't seem to me that it would be a big deal to make the change.
Re: Two ways of receiving arrays on the C ABI
On 2020-10-20 02:16, Ali Çehreli wrote: Everything works at least on Linux. Is this kosher, or am I using some internal knowledge? Yes, you're using some internal knowledge. You cannot assume it works on any other platform or architecture. In theory, the D compiler could choose to change the ABI for passing D arrays and this would break. If fact, the ABI documentation [1] doesn't mention how a D array is passed. A different compiler could choose to pass it differently. [1] https://dlang.org/spec/abi.html#arrays -- /Jacob Carlborg
Re: Can we do compile time reading part of a file using import?
On 2020-10-23 18:42, data pulverizer wrote: For me it's not make-or-break, it just something very useful and I think has clear use case. Please let me know if there are aspects or alternatives I am missing. You could always have the build tool split up the file in multiple smaller files and read one of the smaller files with the import expression. -- /Jacob Carlborg
Re: Template pattern delegate?
On 10/25/20 4:30 AM, frame wrote: Is there a possibility to write templated code / custom trait pattern with usage like a delegate? I have a try-catch block with different types and don't want to repeat myself in every method again. It's always the same, just what's tried changes, eg.: pseudo code: template myStuff(mixin code) { try { code(); } catch (X e) { ... } catch (Y e) { ... } ... } static myStuff!({ writeln("..."); }); That's one of my DConf Onlide slides but for a limited use case! :) int tried(Func, string functionName = __FUNCTION__, string file = __FILE__, size_t line = __LINE__)(Func func) { static if (!is (ReturnType!Func == int)) { pragma(msg, format!"\n%s(%s): Error: %s must return int error code"(file, line, functionName)); static assert(false); } void printError(T)(T err) { stderr.writefln!"\n%s(%s): Failed to execute %s: %s"(file, line, functionName, err); } try { return func(); } catch (Exception exc) { printError(exc.msg); return 1; } catch (Error err) { printError(err); import core.stdc.stdlib : abort; abort(); } assert(false); } Then, all extern(C) functions would be written the same way: extern(C) int foo() { return tried({ // ... return 0; }); } Ali
Re: toStringz lifetime
On Sunday, 25 October 2020 at 10:03:44 UTC, Ali Çehreli wrote: Is it really safe? Imagine a multi-threaded environment where another D function is executed that triggers a GC collection right before the printf. Does the GC see that local variable 'name' that is on the C side? What I don't know is whether the GC is aware only of the stack frames of D functions or the entire thread, which would include the C caller's 'name'. Small note: besides the stack, it is crucial that the GC is aware of the CPU register values. -Johan
Template pattern delegate?
Is there a possibility to write templated code / custom trait pattern with usage like a delegate? I have a try-catch block with different types and don't want to repeat myself in every method again. It's always the same, just what's tried changes, eg.: pseudo code: template myStuff(mixin code) { try { code(); } catch (X e) { ... } catch (Y e) { ... } ... } static myStuff!({ writeln("..."); });
Re: toStringz lifetime
On 10/25/20 3:19 AM, rikki cattermole wrote: On 25/10/2020 11:03 PM, Ali Çehreli wrote: Does the GC see that local variable 'name' that is on the C side? What I don't know is whether the GC is aware only of the stack frames of D functions or the entire thread, which would include the C caller's 'name'. The thread stack frame that is registered with the D GC will know about the D side and may know about the C side. It depends on what the C side is doing. If the C side went ahead and made a new stack frame via a fiber... it won't know about it. But even if it did, the D stack frame is still alive and pinning that bit of memory. Ultimately, if the C side puts that pointer some place like a global or send it to another thread, there are no guarantees that things will play out well. Thanks. That's reassuring. :) So, as long as the D function documents that the C side should make a copy if they want to extend the string's lifetime it's their responsibility. And from your description I understand that they have time to make that copy. Ali
Re: toStringz lifetime
On 25/10/2020 11:03 PM, Ali Çehreli wrote: Does the GC see that local variable 'name' that is on the C side? What I don't know is whether the GC is aware only of the stack frames of D functions or the entire thread, which would include the C caller's 'name'. The thread stack frame that is registered with the D GC will know about the D side and may know about the C side. It depends on what the C side is doing. If the C side went ahead and made a new stack frame via a fiber... it won't know about it. But even if it did, the D stack frame is still alive and pinning that bit of memory. Ultimately, if the C side puts that pointer some place like a global or send it to another thread, there are no guarantees that things will play out well.
toStringz lifetime
toStringz documentation is clear on why, when, and how to extend the lifetime of a D string: https://dlang.org/phobos/std_string.html#.toStringz Assume foo is a D library function that passes a "string" result to e.g. C: extern(C) void foo(ref const(char) * name) { name = format!"file%s.txt"(42).toStringz; // Allocates from GC memory } This may be fine for "immediate use" on the C side because at first glance no garbage collection can take place between our returning the result and their using it: // C caller: const char * name = NULL; foo(&name); // Calls us printf("%s", name); // Uses 'name' immediately Is it really safe? Imagine a multi-threaded environment where another D function is executed that triggers a GC collection right before the printf. Does the GC see that local variable 'name' that is on the C side? What I don't know is whether the GC is aware only of the stack frames of D functions or the entire thread, which would include the C caller's 'name'. Ali
Re: Help on asdf json module
On Sunday, 25 October 2020 at 06:05:27 UTC, Vino wrote: Hi All, Currently we are testing various json module such as "std.json, std_data_json, vibe.data.json and asdf", the below code works perfectely while use "std_data_json or vibe.data.json" but not working as expected when we use "asdf" and throwing the below error, hence request your help on the same. [...] Hi Vino, byElement should be used here for ASDF. foreach(j; jv["items"].byElement) http://asdf.libmir.org/asdf_asdf.html#.Asdf.byElement
Re: Help on asdf json module
On Sunday, 25 October 2020 at 06:05:27 UTC, Vino wrote: Hi All, Currently we are testing various json module such as "std.json, std_data_json, vibe.data.json and asdf", the below code works perfectely while use "std_data_json or vibe.data.json" but not working as expected when we use "asdf" and throwing the below error, hence request your help on the same. The API's are different. You can't just expect one to work with the api of the other. Asdf is a bit more strict in that you have to specify whether you intent to iterate a json object (with `.byKeyValue()`) or a json array (with `.byElement()`). Also the way you fetch values out of it is different. There is `.get!T(default)` that requires a default value in case it is empty (undefined), or `cast(T)field` if you assume there is a value and want an exception throw if not. /+dub.sdl: dependency "asdf" version="~>0.6.6" +/ import std.stdio: writeln; import asdf; import std.conv: to; void main() { string apidata = `{"items":[{"name":"T10","hostname":"test1","type":[{"typeValue":"TD,d...@dev.com,DEVt"},{"typeno":"000"}]},{"name":"T11","hostname":"test2","type":[{"typeValue":"TF,q...@qas.com,QAS"},{"typeno":"100"}]},{"name":"T11","hostname":"test3","type":[{"typeValue":"TP,p...@prd.com,PRD"},{"typeno":"101"}]}]}`; auto jv = parseJson(apidata); foreach(j; jv["items"].byElement()){ writeln(j["name"].get!string("default")); } }
Re: Help on asdf json module
On Sunday, 25 October 2020 at 06:05:27 UTC, Vino wrote: Hi All, Currently we are testing various json module such as "std.json, std_data_json, vibe.data.json and asdf", the below code works perfectely while use "std_data_json or vibe.data.json" but not working as expected when we use "asdf" and throwing the below error, hence request your help on the same. Error: source/app.d(12,2): Error: invalid foreach aggregate jv.opIndex(["items"][]), define opApply(), range primitives, or use .tupleof Maybe library author didn't implement opApply, so you have to iterate using range primitives empty, front, popFront, or handle data using algorithms. You can check examples on the project page https://github.com/libmir/asdf