Re: How to implement Canceleable spawn() from parent
On 6/28/20 4:08 PM, aberba wrote: So I checked receiveTimeout() when I was looking for what I could use. I wish there was an example in the docs. https://dlang.org/library/std/concurrency/receive_timeout.html I have an example of it: http://ddili.org/ders/d.en/concurrency.html#ix_concurrency.receiveTimeout Ali
Re: reference variables don't exist, but can simulate them
On Monday, 29 June 2020 at 02:11:15 UTC, NonNull wrote: Deprecation: Cannot use alias this to partially initialize variable j of type refer. Use j._() This is for the line j=3 What is this about? Where does this hidden rule come from? That one comes from [1]. But there are quite a few more "hidden" rules that you're violating here. Try putting @safe on your main and compiling with -preview=dip1000 (for dmd, refer to your compiler's help if you're using others). The bulk of escape analysis is only done for @safe, and only with that DIP enabled (IIRC only some trivial checks are done otherwise). [1] https://issues.dlang.org/show_bug.cgi?id=19441
Re: reference variables don't exist, but can simulate them
On Sunday, 28 June 2020 at 21:01:36 UTC, NonNull wrote: On Sunday, 28 June 2020 at 20:59:59 UTC, NonNull wrote: Using gdc (Ubuntu 8.4.0-1ubuntu1~18.04) 8.4.0 Please criticize: struct refer(T) { T* ptr; this(ref T x) { ptr = } ref T _() { return *ptr; } alias _ this; string toString() { import std.conv; return to!string(*ptr); } } This will make a reference variable (simulation). [ toString() is just for writeln. ] void main() { int i = 100; refer!int j = i; j = 3; writeln(i); i = 100; writeln(j); j += 3; writeln(i); refer!int k = j; writeln(k); } And a refer!int can be returned as it is just a value. Returning one that contains a pointer to a local variable leads to a compilation error. * does not lead to a compilation error Now with a different compiler I this: Deprecation: Cannot use alias this to partially initialize variable j of type refer. Use j._() This is for the line j=3 What is this about? Where does this hidden rule come from?
[DIP1000] Something I don't quite understand regarding 'scope'
void local(Args...)(Args args) { } void main() @safe { import std.stdio; scope int* p; local(p); // Ok writeln(p); // Error: scope variable p assigned to non-scope parameter _param_0 calling std.stdio.writeln!(int*).writeln } The signatures of `std.stdio.writeln` and `local` are the same (see `writeln` [1]). Yet, with '$ dmd -preview=dip1000' the call to `local` compiles, while the call to `writeln` doesn't. Is that an instance of [2]? [1] https://github.com/dlang/phobos/blob/v2.092.1/std/stdio.d#L3865 [2] https://issues.dlang.org/show_bug.cgi?id=20023
Re: How to implement Canceleable spawn() from parent
On Sunday, 28 June 2020 at 23:39:07 UTC, Stanislav Blinov wrote: On Sunday, 28 June 2020 at 23:02:26 UTC, aberba wrote: I believe this: StopWatch sw; sw.start; works becuse D structs are initialized by default, right? I've never actually done it this way. Little details. Yup. You can also do a auto sw = StopWatch(AutoStart.yes); and not have to call `start` explicitly. Interesting. I should look into Phobos more.
Re: How to implement Canceleable spawn() from parent
On Sunday, 28 June 2020 at 23:02:26 UTC, aberba wrote: I believe this: StopWatch sw; sw.start; works becuse D structs are initialized by default, right? I've never actually done it this way. Little details. Yup. You can also do a auto sw = StopWatch(AutoStart.yes); and not have to call `start` explicitly.
Re: How to implement Canceleable spawn() from parent
On Sunday, 28 June 2020 at 23:02:26 UTC, aberba wrote: On Sunday, 28 June 2020 at 14:23:01 UTC, Stanislav Blinov wrote: On Sunday, 28 June 2020 at 13:29:08 UTC, aberba wrote: Thanks. I believe this: StopWatch sw; sw.start; works becuse D structs are initialized by default, right? I've never actually done it this way. Little details. So I checked receiveTimeout() when I was looking for what I could use. I wish there was an example in the docs. https://dlang.org/library/std/concurrency/receive_timeout.html
Re: How to implement Canceleable spawn() from parent
On Sunday, 28 June 2020 at 14:23:01 UTC, Stanislav Blinov wrote: On Sunday, 28 June 2020 at 13:29:08 UTC, aberba wrote: Thanks. I believe this: StopWatch sw; sw.start; works becuse D structs are initialized by default, right? I've never actually done it this way. Little details.
Re: foreach iterator with closure
To keep this reply brief, I'll just summarize: Lots of great takeaways from both of your posts, and a handful of topics you mentioned that I need to dig into further now. This is great (I too like D :) I very much appreciate the extra insight into how things work and why certain design decisions were made: for me, this is essential for gaining fluency in a language. Thanks again for all your help! Denis
Re: reference variables don't exist, but can simulate them
On Sunday, 28 June 2020 at 20:59:59 UTC, NonNull wrote: Using gdc (Ubuntu 8.4.0-1ubuntu1~18.04) 8.4.0 Please criticize: struct refer(T) { T* ptr; this(ref T x) { ptr = } ref T _() { return *ptr; } alias _ this; string toString() { import std.conv; return to!string(*ptr); } } This will make a reference variable (simulation). [ toString() is just for writeln. ] void main() { int i = 100; refer!int j = i; j = 3; writeln(i); i = 100; writeln(j); j += 3; writeln(i); refer!int k = j; writeln(k); } And a refer!int can be returned as it is just a value. Returning one that contains a pointer to a local variable leads to a compilation error. * does not lead to a compilation error
reference variables don't exist, but can simulate them
Using gdc (Ubuntu 8.4.0-1ubuntu1~18.04) 8.4.0 Please criticize: struct refer(T) { T* ptr; this(ref T x) { ptr = } ref T _() { return *ptr; } alias _ this; string toString() { import std.conv; return to!string(*ptr); } } This will make a reference variable (simulation). [ toString() is just for writeln. ] void main() { int i = 100; refer!int j = i; j = 3; writeln(i); i = 100; writeln(j); j += 3; writeln(i); refer!int k = j; writeln(k); } And a refer!int can be returned as it is just a value. Returning one that contains a pointer to a local variable leads to a compilation error.
Re: foreach iterator with closure
On 6/28/20 9:07 AM, Denis wrote: > * foreach is the actual iterator, Yes. foreach is "lowered" to the following equivalent: for ( ; !range.empty; range.popFront()) { // Use range.front here } A struct can support foreach iteration through its opCall() member function as well. opCall() takes the body of the foreach as a delegate. Because it's a function call, it can take full advantage of the function call stack. This may help with e.g. writing recursive iteration algorithms. http://ddili.org/ders/d.en/foreach_opapply.html#ix_foreach_opapply.opApply > the instantiation of a struct is the > range. Yes. > * When a constructor is not used, the arguments in the call to > instantiate the range (in this case, `hello` in letters(`hello`)) are > mapped sequentially to the member variables in the struct definition > (i.e. to letters.str). Yes, that is a very practical struct feature. I write my structs with as little as needed and provide a constructor only when it is necessary as in your case. > * When a constructor is used, the member variables in the struct > definition are in essence private. Not entirely true. You can still make them public if you want. http://ddili.org/ders/d.en/encapsulation.html > The arguments in the call to > instantiate the range are now mapped directly to the parameters in the > definition of the "this" function. Yes. > * The syntax and conventions for constructors is difficult and > non-intuitive for anyone who hasn't learned Java (or a derivative). C++ uses the name of the class as the constructor: // C++ code struct S { S(); // <-- Constructor S(int); // <-- Another one }; The problem with that syntax is having to rename more than one thing when the name of struct changes e.g. to Q: struct Q { Q(); Q(int); }; And usually in the implementation: Q::Q() {} Q::Q(int) {} D's choice of 'this' is productive. > The > linked document provides a simplified explanation for the "this" > keyword, which is helpful for the first read: > https://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html. I like searching for keywords in my index. The "this, constructor" here links to the constructor syntax: http://ddili.org/ders/d.en/ix.html > * In some respects, the Java syntax is not very D-like. (For example, it > breaks the well-established convention of "Do not use the same name to > mean two different things".) Yes but it competes with another goal: Change as little code as possible when one thing needs to be changed. This is not only practical but helps with correctness. > However, it does need to be learned, > because it is common in D source code. I like D. :p > Here is the complete revised code for the example (in condensed form): > >import std.stdio; > >struct letters { > > string str; > int pos = 1;// Assign here or in this()) > > this(string param1) {// cf. shadow str >str = param1;// cf. this.str = param1 / this.str = str >writeln(`BEGIN`); } > > char front() { return str[pos]; } > void popFront() { pos ++; } > bool empty() { return pos == str.length; } > > ~this() { writeln("\nEND"); }} > >void main() { > foreach (letter; letters(`hello`)) { >write(letter, ' '); }} > > At this point, I do have one followup question: > > Why is the shadow str + "this.str = str" the more widely used syntax in > D, when the syntax in the code above is unambiguous? Because one needs to come up with names like "param7", "str_", "_str", "s", etc. I like and follow D's standard here. > One possible reason that occurred to me is that "str = param1" might > require additional GC, because they are different names. Not at all because there is not memory allocation at all. strings are implemented as the equivalent of the following struct: struct __D_native_string { size_t length_; char * ptr; // ... } So, the "str = param1" assignment is nothing but two 64 bit data transfer, which can easily by optimized away by the compiler in many cases. > But I wouldn't > think it'd make any difference to the compiler. Yes. :) > > Denis Ali
Re: std.concurrency.receive and shared const(char)[]?
On Sunday, 28 June 2020 at 16:39:12 UTC, Anonymouse wrote: On Sunday, 28 June 2020 at 16:11:50 UTC, BakedPineapple wrote: import std.stdio; import std.concurrency; void main() { auto t = spawn((){ receive((shared const(char)[] char_arr) { ownerTid.send(true); }); }); shared const(char)[] char_arr = "cut my code into pieces"; t.send(char_arr); assert(receiveOnly!(bool) == true); } When I run this program, it blocks on the receive() inside the spawned thread. What am I doing wrong? Make the parameter shared(const(char))[] and it will work. I'll leave it to someone who knows more to explain why it behaves that way. ty.
Re: std.concurrency.receive and shared const(char)[]?
On Sunday, 28 June 2020 at 16:11:50 UTC, BakedPineapple wrote: import std.stdio; import std.concurrency; void main() { auto t = spawn((){ receive((shared const(char)[] char_arr) { ownerTid.send(true); }); }); shared const(char)[] char_arr = "cut my code into pieces"; t.send(char_arr); assert(receiveOnly!(bool) == true); } When I run this program, it blocks on the receive() inside the spawned thread. What am I doing wrong? Make the parameter shared(const(char))[] and it will work. I'll leave it to someone who knows more to explain why it behaves that way.
std.concurrency.receive and shared const(char)[]?
import std.stdio; import std.concurrency; void main() { auto t = spawn((){ receive((shared const(char)[] char_arr) { ownerTid.send(true); }); }); shared const(char)[] char_arr = "cut my code into pieces"; t.send(char_arr); assert(receiveOnly!(bool) == true); } When I run this program, it blocks on the receive() inside the spawned thread. What am I doing wrong?
Re: foreach iterator with closure
Many thanks: your post has helped me get past the initial stumbling blocks I was struggling with. I do have a followup question. First, here are my conclusions up to this point, based on your post above, some additional experimentation, and further research (for future reference, and for any other readers). * foreach is the actual iterator, the instantiation of a struct is the range. * When a constructor is not used, the arguments in the call to instantiate the range (in this case, `hello` in letters(`hello`)) are mapped sequentially to the member variables in the struct definition (i.e. to letters.str). * When a constructor is used, the member variables in the struct definition are in essence private. The arguments in the call to instantiate the range are now mapped directly to the parameters in the definition of the "this" function. * The syntax and conventions for constructors is difficult and non-intuitive for anyone who hasn't learned Java (or a derivative). The linked document provides a simplified explanation for the "this" keyword, which is helpful for the first read: https://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html. * In some respects, the Java syntax is not very D-like. (For example, it breaks the well-established convention of "Do not use the same name to mean two different things".) However, it does need to be learned, because it is common in D source code. Here is the complete revised code for the example (in condensed form): import std.stdio; struct letters { string str; int pos = 1;// Assign here or in this()) this(string param1) { // cf. shadow str str = param1; // cf. this.str = param1 / this.str = str writeln(`BEGIN`); } char front() { return str[pos]; } void popFront() { pos ++; } bool empty() { return pos == str.length; } ~this() { writeln("\nEND"); }} void main() { foreach (letter; letters(`hello`)) { write(letter, ' '); }} At this point, I do have one followup question: Why is the shadow str + "this.str = str" the more widely used syntax in D, when the syntax in the code above is unambiguous? One possible reason that occurred to me is that "str = param1" might require additional GC, because they are different names. But I wouldn't think it'd make any difference to the compiler. Denis
Re: Temporary File Creation
On Monday, 22 June 2020 at 23:53:41 UTC, Stanislav Blinov wrote: tempDir just returns a path (i.e. "/tmp" or whatever it is on Windows, etc.), it doesn't create anything. Given the synopsis of std.file, a procedure for *creating* a file doesn't belong there, as it would only be half of an operation. There is a https://dlang.org/library/std/stdio/file.tmpfile.html Thanks.
Re: How to implement Canceleable spawn() from parent
On Sunday, 28 June 2020 at 13:29:08 UTC, aberba wrote: Getting error: Error: template std.concurrency.spawn cannot deduce function from argument types !()(void delegate(Tid id) @system, Tid), candidates are: /usr/include/dmd/phobos/std/concurrency.d(460,5): spawn(F, T...)(F fn, T args) with F = void delegate(Tid) @system, T = (Tid) must satisfy the following constraint: isSpawnable!(F, T) The error you're getting is because you're passing a pointer to a delegate instead of a delegate. Tid id = spawn(, milliseconds, ); ^ here But fixing that still won't compile, because when you want to pass a delegate to `spawn`, it needs to be a shared delegate. If I understood your intent correctly, here's how you can do it: import std.stdio : writeln; import std.concurrency; import core.thread.osthread : Thread; import std.datetime.stopwatch; auto setInterval(long milliseconds, void function() callback) { static void worker(Duration d, void function() cb) { writeln("Starting ", thisTid, "..."); bool done = false; StopWatch sw; sw.start; while (true) { // wait for messages for a timespan of at least `d` receiveTimeout( d, (string text) { writeln("Received string: ", text); if (text == "cancel") done = true; }); if (done) break; // a non-cancelling message might've been received before timeout, // so test if it's really time for the callback if (sw.peek >= d) { cb(); sw.reset; } } } Tid id = spawn(, milliseconds.msecs, callback); return id; } void stopInterval(Tid tid) { send(tid, "cancel"); } void main() { auto tid = setInterval(1000, { writeln("tick"); }); Thread.sleep(2.seconds); send(tid, "not cancel"); Thread.sleep(5.seconds); stopInterval(tid); }
How to implement Canceleable spawn() from parent
Trying to implement a setInterval() that I can cancel using: Tid tid = setInterval(2000, (){ writeln("hello");}) And then I can do: stopInterval(tid); With something like this: stopInterval(Tid tid) { send(tid, "cancel"); } import std.stdio : writeln; import std.concurrency : receive, spawn, thisTid, Tid; auto setInterval(long milliseconds, void delegate() callback) { auto worker(long mls, void delegate() cb) { import core.thread.osthread : Thread; import std.datetime : seconds, msecs; writeln("Starting ", thisTid, "..."); bool done = false; receive((string text) { writeln("Received string: ", text); done = true; }); do { // or receive() comes here? Thread.sleep(mls.msecs); cb(); } while (!done); } // I guess issue is with the callback Tid id = spawn(, milliseconds, ); return id; } Getting error: Error: template std.concurrency.spawn cannot deduce function from argument types !()(void delegate(Tid id) @system, Tid), candidates are: /usr/include/dmd/phobos/std/concurrency.d(460,5):spawn(F, T...)(F fn, T args) with F = void delegate(Tid) @system, T = (Tid) must satisfy the following constraint: isSpawnable!(F, T) Am I even using the right tool here?
Re: Translating C headers to D: How do I compile it?
On Sunday, 28 June 2020 at 05:13:32 UTC, Mike Parker wrote: On Sunday, 28 June 2020 at 04:59:12 UTC, Kirill wrote: something.d: module something; int add(int a, int b); This should be extern(C) int add(int a, int b). The extern(C) tells the D compiler to use the standard C calling convention when calling that function. Thanks! It all works now! 'extern(C)' is what was missing.
Re: Light-weight runtime
On Sunday, 28 June 2020 at 07:09:53 UTC, Виталий Фадеев wrote: I want light-weight runtime ! How to ? If you have access to Google translate or any equivalent tool, you may use it to write in Russian language and copy+paste the English here. I think that'll really help. I always give deep respect to people with different native languages who're trying really well to write English here. Considering someone of us learnt and wrote English in school but still suck at it. My biggest problem is typos. --;;:: Now I think your question was discussed recently here https://forum.dlang.org/thread/gxtgbthyytukmqmzp...@forum.dlang.org
dmd release schedule?
Is there a release schedule anywhere for DMD? Any list of tasks to be the next release? I'm only finding 5+ year old things when searching.
Light-weight runtime
I want light-weight runtime ! How to ?