Basic SQLite Application
I'm creating an application in D to do some purchase management stuff and I ran into a snag pretty early on. I'm trying to use sqlite via [this library](https://github.com/adamdruppe/arsd/blob/master/sqlite.d). I started trying to get it to compile in another directory structure but since I've switched to dub and made a few tweaks, it compiles and runs and returns some large negative number as an error without printing what's in the writeln. Here is my dub file: ``` { "authors": [ "onesadman" ], "dflags" : ["-m64"], "copyright": "Copyright © 2022, onesadman", "description": "Costco Purchase History", "license": "proprietary", "name": "cph", "libs-windows": ["lib/sqlite3"], "copyFiles":["lib/sqlite3.lib"] } ``` Here is my program: ``` import std.stdio; import arsd.sqlite; void main() { writeln("Edit source/app.d to start your project."); } ``` I also have database.d and sqlite.d in my source/arsd directory and a lib folder with sqlite3.lib in it. It is successfully copied to the root folder and I also copied sqlite3.dll from c:\windows\sysWOW64\winsqlite3.dll into the root folder just in case I was doing it wrong and that fixed it. It seems I must be close as I have it compiling. I'm not sure where it's going to look for the lib folder. I have run it with dub and with dub build --arch=x86_64 and then running the cph.exe directly. I won't rule out that my lib file is the wrong file as I don't know how to tell or find the right one.
Re: Templatized delegates
On Tuesday, 31 May 2022 at 23:15:24 UTC, Andrey Zherikov wrote: On Tuesday, 31 May 2022 at 21:53:17 UTC, Paul Backus wrote: If you want compile-time polymorphism, three's no other way. Yes, I want compile-time polymorphism. In case if `S.doSomething` is NOT template function then the problem can be solved easily by wrapping access to `S` into another delegate: ```d import std.stdio: writeln; struct S { void doSomething(int value) { value.writeln; } } alias DG = void delegate (void delegate(int) doSomething); auto createDG(T)(T value) { return delegate (void delegate(int) doSomething) { doSomething(value); }; } struct R { DG dg; this(int value) { dg = createDG(value); } } void main() { auto r = R(5); S s; r.dg(_ => s.doSomething(_)); } ``` How to do the same for templated `S.doSomething`?
Re: Templatized delegates
On Tuesday, 31 May 2022 at 22:34:41 UTC, Christian Köstlin wrote: Would it help to not create the delegate in R's constructor, but feed the delegate into it (and create the delegate outside). This would also resemble your description (R is a delegate holder) more. That's possible but the problem is that `S` is part of `DG`.
Re: Templatized delegates
On Tuesday, 31 May 2022 at 21:53:17 UTC, Paul Backus wrote: If you want compile-time polymorphism, three's no other way. Yes, I want compile-time polymorphism. ```d import std.stdio; struct S { // function that should be called from delegate void doSomething(T)(T value) { value.writeln; } } interface I { void doSomething(int value); } class Adapter : I { S s; this(S s) { this.s = s; } void doSomething(int value) { s.doSomething(value); } } alias DG = void delegate (I i); auto createDG(int value) { return delegate (I i) { i.doSomething(value); }; } struct R { DG dg; this(int value) { dg = createDG(value); } } void main() { auto r = R(5); S s; r.dg(new Adapter(s)); } ``` Unfortunately this solution looses important feature: there is no more templated call to `S.doSomething` as `I.doSomething` is not template and adding override for every type is not maintainable.
Re: Templatized delegates
On 2022-05-31 23:15, Andrey Zherikov wrote: I have tightly coupled code which I'd like to decouple but I'm a bit stuck. For simplicity, I reduced the amount of code to something simple to understand. So I have a struct `S` that has templated member function that does something. On the other side I have delegate holder `R` - this delegate takes `S` object as an argument and calls that function. My goal is to remove dependency from `R` to `S`. Here is code example: ```d import std.stdio: writeln; struct S { // function that should be called from delegate void doSomething(T)(T value) { value.writeln; } } alias DG = void delegate (ref S s); auto createDG(T)(T value) { return delegate (ref S s) { s.doSomething(value); }; } struct R { DG dg; this(int value) { dg = createDG(value); } } void main() { auto r = R(5); S s; r.dg(s); } ``` An obvious way is to add a type template parameter to `R`, `DG` and `createDG` but I would like to avoid this. Is there another way to do so? I think ideal solution would be having templatized delegate `void delegate (S)(ref S s)` and then call `r.dg!S(s)` but it's not available: `alias DG = void delegate (S) (ref S s)` gives unclear `Error: function declaration without return type. (Note that constructors are always named 'this')` message.Would it help to not create the delegate in R's constructor, but feed the delegate into it (and create the delegate outside). This would also resemble your description (R is a delegate holder) more.
Re: Templatized delegates
On Tuesday, 31 May 2022 at 21:15:24 UTC, Andrey Zherikov wrote: I have tightly coupled code which I'd like to decouple but I'm a bit stuck. For simplicity, I reduced the amount of code to something simple to understand. So I have a struct `S` that has templated member function that does something. On the other side I have delegate holder `R` - this delegate takes `S` object as an argument and calls that function. My goal is to remove dependency from `R` to `S`. [...] An obvious way is to add a type template parameter to `R`, `DG` and `createDG` but I would like to avoid this. Is there another way to do so? If you want compile-time polymorphism, three's no other way. If you're ok with runtime polymorphism, you could replace S with something like an interface or a sum type. For example: ```d import std.stdio; struct S { // function that should be called from delegate void doSomething(T)(T value) { value.writeln; } } interface I { void doSomething(int value); } class Adapter : I { S s; this(S s) { this.s = s; } void doSomething(int value) { s.doSomething(value); } } alias DG = void delegate (I i); auto createDG(int value) { return delegate (I i) { i.doSomething(value); }; } struct R { DG dg; this(int value) { dg = createDG(value); } } void main() { auto r = R(5); S s; r.dg(new Adapter(s)); } ```
Re: Tracing/Profiling D Applications
On 2022-05-29 23:00, Ali Çehreli wrote: On 5/29/22 13:53, Christian Köstlin wrote: > According to > https://www.schveiguy.com/blog/2022/05/comparing-exceptions-and-errors-in-d/ > its bad to catch Errors ... Correct in the sense that the program should not continue after catching Error. > so dowork should catch only Exception? It should catch Error as well. Otherwise you will have no idea why a thread disappeared. You may agree with me here: https://youtu.be/dRORNQIB2wA?t=1950 Thanks a lot for this explanation! Probably a try catch (Throwable) is a good thing to have in any thread that does not only use nothrows ... I catch'ed Throwable in the code just because it's a quick little experiment. > it might be better > to crash directly ... Sounds good but only after leaving the reason behind somehow. Ali Kind regards, Christian
Re: Tracing/Profiling D Applications
On 2022-05-29 23:08, Ali Çehreli wrote: On 5/29/22 13:47, Christian Köstlin wrote: > Our discussion with using TLS for the > collectors proposed to not need any lock on the add method for > collector, because its thread local and with that thread safe? It would be great that way but then the client changed the requirements on us: On 5/26/22 12:54, Christian Köstlin wrote: > I want to be able to dump tracings even while the program is still running. :p If the collected data were TLS, then the dumping thread should be able to ask each thread to provide data collected so far. That either requires synchronization, which I did, which necessitated shared Collector objects; or messaging, which would require each thread checking their Concurrency message box. I don't know... A third option came to me: Each thread periodically puts their data to a common location and dumper dumps whatever is aggregated up to that point. This would reduce contention. Thats also a nice idea, e.g. the collectors could aggregate their data and only propagate it once every second or every 10 seconds, or every 1000 events or something! Will think about that some more! Thanks a lot! Christian
Templatized delegates
I have tightly coupled code which I'd like to decouple but I'm a bit stuck. For simplicity, I reduced the amount of code to something simple to understand. So I have a struct `S` that has templated member function that does something. On the other side I have delegate holder `R` - this delegate takes `S` object as an argument and calls that function. My goal is to remove dependency from `R` to `S`. Here is code example: ```d import std.stdio: writeln; struct S { // function that should be called from delegate void doSomething(T)(T value) { value.writeln; } } alias DG = void delegate (ref S s); auto createDG(T)(T value) { return delegate (ref S s) { s.doSomething(value); }; } struct R { DG dg; this(int value) { dg = createDG(value); } } void main() { auto r = R(5); S s; r.dg(s); } ``` An obvious way is to add a type template parameter to `R`, `DG` and `createDG` but I would like to avoid this. Is there another way to do so? I think ideal solution would be having templatized delegate `void delegate (S)(ref S s)` and then call `r.dg!S(s)` but it's not available: `alias DG = void delegate (S) (ref S s)` gives unclear `Error: function declaration without return type. (Note that constructors are always named 'this')` message.
Re: Execute the Shell command and continue executing the algorithm
On Tuesday, 31 May 2022 at 15:29:16 UTC, frame wrote: On Monday, 30 May 2022 at 11:18:42 UTC, Alexander Zhirov wrote: if (here is my condition termination of the program) OT: Wouldn't it be great to have ArnoldC support? ;-) i'm pretty sure the terminattor is more efficient than kill -9 lmaof
Re: Execute the Shell command and continue executing the algorithm
On Monday, 30 May 2022 at 11:18:42 UTC, Alexander Zhirov wrote: if (here is my condition termination of the program) OT: Wouldn't it be great to have ArnoldC support? ;-)
Re: Execute the Shell command and continue executing the algorithm
On 2022-05-30 15:25, Ali Çehreli wrote: On 5/30/22 04:18, Alexander Zhirov wrote: > I want to run a command in the background The closest is spawnShell: import std.stdio; import std.process; import core.thread; void main() { auto pid = spawnShell(`(sleep 1 & echo SLEEP >> log)`); Thread.sleep(5.seconds); kill(pid); writeln("Terminated with ", wait(pid)); } I am not good at shell scripting but I had to change your && to & to see anything in log. I think this runs sleep 1 in the background and emits the echo directly. As std.process documentation explains, the value returned by wait() (and more) are platform dependent. Ali
Re: static assert("nothing")
On Tuesday, 31 May 2022 at 08:51:45 UTC, realhet wrote: Hi, In my framework I just found a dozen of compile time error handling like: ...else static assert("Invalid type"); This compiles without error. And it was useless for detecting errors because I forgot the first "false" or "0" parameter. I think it is because of the weird case of "every string casted to bool is true". There is an example in Phobos also: https://github.com/dlang/phobos/blob/master/std/uni/package.d at line 8847: static assert("Unknown normalization form "~norm); It is easy to make this mistake, but does static assert(string) has any meaningful use cases? This is what Zig does, actually: https://ziglang.org/documentation/0.9.1/#compileError ```Zig const std = @import("std"); const expect = std.testing.expect; test "comptime vars" { var x: i32 = 1; comptime var y: i32 = 1; x += 1; y += 1; try expect(x == 2); try expect(y == 2); if (y != 2) { // This compile error never triggers because y is a comptime variable, // and so `y != 2` is a comptime value, and this if is statically evaluated. @compileError("wrong y value"); } } ```
Re: static assert("nothing")
On Tuesday, 31 May 2022 at 09:52:10 UTC, realhet wrote: On Tuesday, 31 May 2022 at 09:35:30 UTC, Andrea Fontana wrote: On Tuesday, 31 May 2022 at 08:51:45 UTC, realhet wrote: Check if that string is init. assert("", "cool"); assert("ehh", "cool"); assert(string.init, "Not cool"); I feel some "JavaScript equality operator" vibes in this :D Anyways, I will be extra careful with these. assert(string.init is null) is the answer :)
Re: static assert("nothing")
On Tuesday, 31 May 2022 at 09:35:30 UTC, Andrea Fontana wrote: On Tuesday, 31 May 2022 at 08:51:45 UTC, realhet wrote: Check if that string is init. assert("", "cool"); assert("ehh", "cool"); assert(string.init, "Not cool"); I feel some "JavaScript equality operator" vibes in this :D Anyways, I will be extra careful with these.
Re: static assert("nothing")
On Tuesday, 31 May 2022 at 08:51:45 UTC, realhet wrote: Hi, In my framework I just found a dozen of compile time error handling like: ...else static assert("Invalid type"); This compiles without error. And it was useless for detecting errors because I forgot the first "false" or "0" parameter. The first is the assert condition, the message is opt. I think it is because of the weird case of "every string casted to bool is true". string s1; string s2 = string.init; // Equivalent string s3 = null; // Equivalent string s4 = ""; assert(s1, "This fails"); assert(s2, "This fails too"); assert(s3, "This fails too"); assert(s4, "This pass"); There is an example in Phobos also: https://github.com/dlang/phobos/blob/master/std/uni/package.d at line 8847: static assert("Unknown normalization form "~norm); It is easy to make this mistake, but does static assert(string) has any meaningful use cases? Check if that string is init. Andrea
Re: static assert("nothing")
On Tuesday, 31 May 2022 at 09:11:41 UTC, JG wrote: On Tuesday, 31 May 2022 at 08:51:45 UTC, realhet wrote: Hi, In my framework I just found a dozen of compile time error handling like: ...else static assert("Invalid type"); This compiles without error. And it was useless for detecting errors because I forgot the first "false" or "0" parameter. I think it is because of the weird case of "every string casted to bool is true". There is an example in Phobos also: https://github.com/dlang/phobos/blob/master/std/uni/package.d at line 8847: static assert("Unknown normalization form "~norm); It is easy to make this mistake, but does static assert(string) has any meaningful use cases? I was going to suggest to do something like: ```d import std; string compileError(string msg) { import std.format; return format("static assert(0,%(%s%));",[msg]); } auto doGreatThings(T)(T x) { static if(is(T==int)) { return "great things!"; } else mixin(compileError("Invalid type.")); } void main() { doGreatThings!int(123).writeln; doGreatThings!string("oh dear").writeln; } ``` But (a) why should you need to and (b) this makes the message more obscure. onlineapp.d-mixin-14(14): Error: static assert: "Invalid type." onlineapp.d(20):instantiated from here: `doGreatThings!string` And then suddenly everyone has their own version of compileError. There's no reason the compiler can't check whether the first expression given evaluates to string and if so then the first argument moves to the second argument and the first argument becomes 0. `extern (D) this(const ref Loc loc, Expression exp, Expression msg)`
Re: static assert("nothing")
On Tuesday, 31 May 2022 at 08:51:45 UTC, realhet wrote: Hi, In my framework I just found a dozen of compile time error handling like: ...else static assert("Invalid type"); This compiles without error. And it was useless for detecting errors because I forgot the first "false" or "0" parameter. I think it is because of the weird case of "every string casted to bool is true". There is an example in Phobos also: https://github.com/dlang/phobos/blob/master/std/uni/package.d at line 8847: static assert("Unknown normalization form "~norm); It is easy to make this mistake, but does static assert(string) has any meaningful use cases? I was going to suggest to do something like: ```d import std; string compileError(string msg) { import std.format; return format("static assert(0,%(%s%));",[msg]); } auto doGreatThings(T)(T x) { static if(is(T==int)) { return "great things!"; } else mixin(compileError("Invalid type.")); } void main() { doGreatThings!int(123).writeln; doGreatThings!string("oh dear").writeln; } ``` But (a) why should you need to and (b) this makes the message more obscure. onlineapp.d-mixin-14(14): Error: static assert: "Invalid type." onlineapp.d(20):instantiated from here: `doGreatThings!string`
Re: static assert("nothing")
On Tuesday, 31 May 2022 at 08:51:45 UTC, realhet wrote: Hi, In my framework I just found a dozen of compile time error handling like: ...else static assert("Invalid type"); This compiles without error. And it was useless for detecting errors because I forgot the first "false" or "0" parameter. I think it is because of the weird case of "every string casted to bool is true". There is an example in Phobos also: https://github.com/dlang/phobos/blob/master/std/uni/package.d at line 8847: static assert("Unknown normalization form "~norm); It is easy to make this mistake, but does static assert(string) has any meaningful use cases? I agree that static assert should have a special case for handling strings, so we have both these signatures: `static assert(value, message)` and `static assert(message)`
static assert("nothing")
Hi, In my framework I just found a dozen of compile time error handling like: ...else static assert("Invalid type"); This compiles without error. And it was useless for detecting errors because I forgot the first "false" or "0" parameter. I think it is because of the weird case of "every string casted to bool is true". There is an example in Phobos also: https://github.com/dlang/phobos/blob/master/std/uni/package.d at line 8847: static assert("Unknown normalization form "~norm); It is easy to make this mistake, but does static assert(string) has any meaningful use cases?