Re: why is "hello".writeln considered bad?
On Friday, 20 November 2020 at 07:39:10 UTC, norm wrote: I was reading some posts and this was presented as a snippet of code and was immediately flagged as bad practice. Eh, I wouldn't quite put it that way. If we're thinking of the same thread, one person said he thought it was a bad idea. That doesn't make it bad practice. It's just his opinion. I think UFCS is an awesome feature. And it's widely used in D code. I get some people don't like it but occasionally I prefer this syntax. It feels more declarative and fluent in style. Is there a good technical reason why it is bad practice, e.g. does it make it easier to write bugs? Or is it just what people are used to? I think everyone has their own criteria for when to use UFCS. For example, I don't generally write "foo".writeln myself, because I don't think of writeln as being a property of strings. And that's the lens through which I view UFCS: this operation is akin to a property of this type. Other people might not see it that way, and one (not me) could make an argument that this specific usage is bad practice, but the feature itself rocks.
why is "hello".writeln considered bad?
I was reading some posts and this was presented as a snippet of code and was immediately flagged as bad practice. I get some people don't like it but occasionally I prefer this syntax. It feels more declarative and fluent in style. Is there a good technical reason why it is bad practice, e.g. does it make it easier to write bugs? Or is it just what people are used to? Thanks, norm
Re: DMD -i option, simple question...
On Friday, 20 November 2020 at 03:06:37 UTC, WhatMeWorry wrote: The "..when this option is enabled..." is exactly the behavior I want, but how is it enabled? Is there an "all inclusive pattern" that I'm missing. dmd -i yourfile.d that's the default it is describing when you don't specify any pattern.
DMD -i option, simple question...
The DMD forum mentions internal design. This is more of a beginner usage question. - from Compiler Switches - -I=directory Look for imports also in directory -i[=pattern ] Enables "include imports" mode, where the compiler will include imported modules in the compilation, as if they were given on the command line. By default, when this option is enabled, all imported modules are included except those in druntime/phobos The "..when this option is enabled..." is exactly the behavior I want, but how is it enabled? Is there an "all inclusive pattern" that I'm missing.
Re: Calling function within class.
On Thursday, 19 November 2020 at 19:51:24 UTC, Vino wrote: the moment we enable parallelism, it is throwing an error on the SQL part (Fetch the username/ password from the table for each account), as it could not execute the SQL query in parallel for different account. I see no reason for a SELECT call (UPDATE/INSERT could cause locks...). Which error do you get?
Re: Calling function within class.
On Wednesday, 18 November 2020 at 21:33:58 UTC, Ali Çehreli wrote: On 11/18/20 7:01 AM, Vino wrote: >Request your help on how to call a function(listFile) from another > function(getFilelist) within the same class(GetDirlist), below is an > example code. That code looks unnecessarily complex to me. First of all, parallel() already executes the loop body in separate threads, so I don't see any reason for Task in that code. std.parallel will appear during my DConf presentation on Saturday. The following program applies ideas from some of my slides and just works in parallel: import std.process; import std.exception; import std.format; import std.parallelism; import std.stdio; class GetDirlist { @system private auto listFile(immutable string st) { auto fl = execute(["ls","-l"]); enforce(fl.status == 0, format("File not Found: %s", fl.status)); return fl.output; } @system public auto getFilelist() { // I am using D dynamic arrays for simpliticy auto flstore = [ "/path1/Dir1", "path2/Dir2" ]; // Note preallocated slot for each result: auto amidata = new string[flstore.length]; // Taking advantage of automatic loop counter foreach(i, st; parallel(flstore,1)) { // Each execution assigns to its own slot amidata[i] = listFile(st); } return amidata[]; } } void main() { // Need an object to call a non-static member function: auto g = new GetDirlist(); writeln(g.getFilelist()); } Ali Hi Ali, Thank you very much, your solution works for my example, but it does not work for the main goal, let me explain what we are trying to perform. Nut shell: Try to execute an aws command on sever accounts in parallel to get some data. Noe: each account has as separate username and password store in a database table(encrypted). Cod Logic Fetch the username/ password from the table for each account. Get the “awssecrete” key and “accesskey” for each account by calling an aws api using the above username/password. Set the fetched key’s as an environment variable. Execute the aws command and get the data for each of the account As we have many accounts what we are trying is to get the data in parallel(execute the aws command in parallel for each account and store the result in a array). At present our code is working fine(without parallel), the moment we enable parallelism, it is throwing an error on the SQL part (Fetch the username/ password from the table for each account), as it could not execute the SQL query in parallel for different account. If there is any other logic please do let me know will give it a try. Below is the SQL code. @trusted public auto getAwsconf(immutable string account) { auto con = new GetConnections(); Statement stmt = con.db.prepare("SELECT username,AES_DECRYPT(b.userpass,b.key,b.vector) AS passwd FROM config WHERE account = :account"); stmt.setParameter("account", account); RowSet awsaccount = stmt.query(); scope(exit) con.db.close(); return awsaccount; } From, Vino.B
Re: betterC question
On Thursday, 19 November 2020 at 14:34:38 UTC, Adam D. Ruppe wrote: On Thursday, 19 November 2020 at 00:20:50 UTC, Dibyendu Majumdar wrote: Okay thanks. Bad idea IMO. That's kinda how I see C taking the address of various things implicitly. To be honest it seems irrelevant what C does.
Re: implementing default opCmp
On 11/19/20 6:12 AM, Steven Schveighoffer wrote: On 11/18/20 6:06 PM, ag0aep6g wrote: int opCmp(S other) { import std.typecons: tuple; return tuple(this.tupleof).opCmp(tuple(other.tupleof)); } Ah, excellent solution! I hadn't thought of that. -Steve That's what I use as well. S can be replaced with something like 'typeof(this)' (or perhaps 'ref const(typeof(this))' and throw some inout in there :) ) and the whole thing can be mixed-in whereever needed. Ali
Re: Function Pointer Not Working
I will wait with this code. WaitForSingleObject(threading, INFINITE);
Re: betterC question
On Thursday, 19 November 2020 at 14:34:38 UTC, Adam D. Ruppe wrote: On Thursday, 19 November 2020 at 00:20:50 UTC, Dibyendu Majumdar wrote: Okay thanks. Bad idea IMO. That's kinda how I see C taking the address of various things implicitly. good example
Re: Function Pointer Not Working
On Thursday, 19 November 2020 at 15:51:09 UTC, Kagamin wrote: The delegate is stored on the stack of the calling thread, the created thread loads it from there, but the calling thread doesn't wait for that and clobbers the stack right away. If you were lucky your code would crash. The thread that I do wait ultil function is finished. Using a while with 3 seconds to verify if thread id is in running list, and break if not finishing owner thread.
Re: Function Pointer Not Working
The delegate is stored on the stack of the calling thread, the created thread loads it from there, but the calling thread doesn't wait for that and clobbers the stack right away. If you were lucky your code would crash.
Re: betterC question
On Thursday, 19 November 2020 at 00:20:50 UTC, Dibyendu Majumdar wrote: Okay thanks. Bad idea IMO. That's kinda how I see C taking the address of various things implicitly.
Re: implementing default opCmp
On 11/18/20 6:06 PM, ag0aep6g wrote: On Wednesday, 18 November 2020 at 22:29:17 UTC, Steven Schveighoffer wrote: How do I do something really simple for opCmp? I tried this it didn't work: return this == other ? 0 : this.tupleof < other.tupleof ? -1 : 1; std.typecons.Tuple has opCmp. So this works: int opCmp(S other) { import std.typecons: tuple; return tuple(this.tupleof).opCmp(tuple(other.tupleof)); } Ah, excellent solution! I hadn't thought of that. -Steve
Re: implementing default opCmp
On 11/18/20 6:02 PM, Paul Backus wrote: On Wednesday, 18 November 2020 at 22:29:17 UTC, Steven Schveighoffer wrote: I have a struct like this: struct S { int x; int y; } and I want a default comparison. The problem is, that comparison doesn't have a default, and requires I implement opCmp. While this is useful for the compiler, there's no default I know of that is an easy one-liner. Here's a stab at a totally generic version that I haven't unit tested at all, except to verify that it works for your example struct S: auto cmp(T, U)(auto ref T lhs, auto ref U rhs) { import core.lifetime: forward; static if (__traits(compiles, lhs.opCmp(rhs))) return forward!lhs.opCmp(forward!rhs); else static if (__traits(compiles, rhs.opCmp(lhs))) return -forward!rhs.opCmp(forward!lhs); else return lhs < rhs ? -1 : lhs > rhs ? 1 : 0; } mixin template defaultOpCmp() { import std.traits: isAggregateType; static assert(isAggregateType!(typeof(this)), "opCmp can only be overloaded for aggregate types."); auto opCmp()(auto ref typeof(this) other) { import std.traits: ReturnType, CommonType, Fields; import std.meta: Map = staticMap; alias cmpType(T) = ReturnType!((T lhs, T rhs) => cmp(lhs, rhs)); alias Result = CommonType!(Map!(cmpType, Fields!(typeof(this; Result result; static foreach (i, _; typeof(this).tupleof) if (result == 0) result = cmp(this.tupleof[i], other.tupleof[i]); return result; } } Yeah, something like this might be useful in druntime. But it makes you wonder if we wouldn't be better off without opCmp but instead with opBinary(string s : "<") and friends. One thing that sucks is that opCmp might do more operations than are necessary for the actual comparison, because it has to generate the numeric result. -Steve
Re: Function Pointer Not Working
Solved replacing this line: CreateThread(null, 0, &_fun, , 0, null); to this code: task!({CreateThread(null, 0, &_fun, , 0, null);}).executeInNewThread();
Re: betterC question
On Thursday, 19 November 2020 at 00:07:12 UTC, Dibyendu Majumdar wrote: I have simple test program: import core.stdc.stdio : printf; void test() { int* a; printf("a == null %d\n", a == null); } int function() fp = test; extern (C) void main() { fp(); } Why do I get: \d\dmd-2.092.1\windows\bin64\dmd.exe -betterC tests.d tests.d(5): Error: printf cannot be interpreted at compile time, because it has no available source code This is on Windows IMO another problem here is that `function` and `delegate` are special cases of the `*` postfix. With a syntax like int()* fp = test it would be more obvious to new comers that `&` is missing. This is a syntax I experiment in STYX for example [1]. Note that then there's also the problem with functions pointers requiring a context. This context is not necessarily a `this` (for closures it's a frame obviously). [1] https://gitlab.com/basile.b/styx/-/blob/master/tests/backend/function_pointers.sx#L10
Re: betterC question
On Thursday, 19 November 2020 at 09:23:25 UTC, Jacob Carlborg wrote: Yes, calling `writeln` like that is a bad idea. That was a bad example. But the actual reason is, this is how D implements properties [1]. Any function that doesn't take an argument can be called without parentheses. Any function which takes a single argument can be called like setting a field. I think that properties on an object are a special case - but treating an random function identifier as callable is still bad.
Re: betterC question
On Thursday, 19 November 2020 at 01:42:16 UTC, Mike Parker wrote: On Thursday, 19 November 2020 at 00:20:50 UTC, Dibyendu Majumdar wrote: On Thursday, 19 November 2020 at 00:18:54 UTC, rikki cattermole wrote: You don't need the brackets to call a function (and with a little help from UFCS): void main() { import std.stdio; "Hello!".writeln; writeln; } Okay thanks. Bad idea IMO. Imagine what range pipelines would look like without it. This is one of my favorite D features. Well Java and C# have streams and it looks perfectly fine without this kind of syntax.
Re: betterC question
On Thursday, 19 November 2020 at 00:20:50 UTC, Dibyendu Majumdar wrote: On Thursday, 19 November 2020 at 00:18:54 UTC, rikki cattermole You don't need the brackets to call a function (and with a little help from UFCS): void main() { import std.stdio; "Hello!".writeln; writeln; } Okay thanks. Bad idea IMO. Yes, calling `writeln` like that is a bad idea. That was a bad example. But the actual reason is, this is how D implements properties [1]. Any function that doesn't take an argument can be called without parentheses. Any function which takes a single argument can be called like setting a field. Here's an example: struct Color { private uint hex; int red() out(result; result >= 0 && result <= 255) // assert that the result is within bounds { return (hex & 0xFF) >> 16; } void red(int value) in(value >= 0 && value <= 255) // assert that the value is within bounds { hex = (hex & 0x00) | (value << 16); } // similar functions for green and blue } void main() { Color color; color.red = 255; assert(color.red == 255); } [1] https://en.wikipedia.org/wiki/Property_(programming) -- /Jacob Carlborg
Re: Calling function within class.
On Wednesday, 18 November 2020 at 19:25:06 UTC, Vino wrote: The above code is a sample code, but the logic is same, correct me if my understanding is wrong, in the above code "obj" is a an object for the class GetDirlist, so we are accessing the class member using "obj.listFile(st)" , so why do we need the "(this)" and also why is this so complicated in D where as in PHP it is simple like below You need to understand that you cannot use "this" in a function that you call in a new thread but task! starts a kind of new thread. That's not allowed by the runtime. Your PHP code does not show any threading and PHP does not support threading without extensions. Also PHP does not allow $this for real threading extensions like parallel. For D that means... // before that statement you can call "this" - it points to your GetDirlist class. auto fltask = task!( // this function is called in the new thread // and it's enclosed in the body of task! but could be also just a pointer to another // function. This is valid as long as the compiler do not need to access outside // variables/scope. "this" would also access the outside scope. function(GetDirlist obj, string st) { obj.listFile(st); } // end of function and thread ) // after that statement you can call "this" again // so we pass "this" (your object) as argument to the function that cannot access "this" // and the string that the function is expecting (this, "foo");
Re: Can't pass [] to extern function object method
On Thursday, 19 November 2020 at 07:46:20 UTC, Bastiaan Veelo wrote: On Wednesday, 18 November 2020 at 10:50:12 UTC, frame wrote: I found the "bug". It was caused by a debug {} statement within a struct method. I assume that the debug symbol is just incompatible called from the DLL context. Were the DLL and main program built in different modes (debug/release)? Then this problem is understandable. Otherwise I find this surprising, and probably worth a bug report? — Bastiaan. No, but the DLL was compiled with -debug flag which enables an additional member that the main program cannot see. I think that is the explaination. In fact the flag was not set on the main program.