Re: Dscanner: is it possible to switch off style checks case-by-case?
On Saturday, 15 February 2020 at 07:23:02 UTC, Basile B. wrote: On Thursday, 13 February 2020 at 17:15:50 UTC, mark wrote: I'm starting out with GtkD and have this function: [snip] Otherwise here is an example of how you can tune the different checks: https://raw.githubusercontent.com/dlang/phobos/master/.dscanner.ini See also the last section of https://raw.githubusercontent.com/dlang-community/D-Scanner/master/README.md Thank you, I made the code changes and am reading the docs you linked to.
Difference between range `save` and copy constructor
I am interested in current circumstances when we have new copy constructor feature what is the purpose of having range `save` primitive? For me they look like doing basicaly the same thing. And when looking in some source code of `range` module the most common thing that `save` does is that it use constructor typeof(this) to create a new instance and use `save` on the source range: https://github.com/dlang/phobos/blob/v2.090.1/std/range/package.d So what is conceptual difference between `save` and copy contructor of range?
How the hell to split multiple delims?
I've tried 10 different ways with split and splitter, I've used all the stuff that people have said online but nothing works. I always get a template mismatch error. Why is something so easy to do so hard in D? auto toks = std.regex.split(l, Regex("s")); auto toks = std.regex.splitter(l, Regex("s")); auto toks = std.regex.splitter(l, ctRegex!r"\.");
Re: How the hell to split multiple delims?
On Saturday, 15 February 2020 at 11:32:42 UTC, AlphaPurned wrote: I've tried 10 different ways with split and splitter, I've used all the stuff that people have said online but nothing works. I always get a template mismatch error. Why is something so easy to do so hard in D? auto toks = std.regex.split(l, Regex("s")); auto toks = std.regex.splitter(l, Regex("s")); auto toks = std.regex.splitter(l, ctRegex!r"\."); Why do you think this doesn't work? I'm not just asking this to be rude. Your problem is likely in the rest of your code. $ rdmd --eval 'split("the quick,brown:fox",regex("[ ,:]")).writeln' ["the", "quick", "brown", "fox"] $ rdmd --eval 'typeid(split("the quick,brown:fox",regex("[ ,:]"))).writeln' immutable(char)[][] $ rdmd --eval 'splitter("the quick,brown:fox",regex("[ ,:]")).writeln' ["the", "quick", "brown", "fox"] $ rdmd --eval 'typeid(splitter("the quick,brown:fox",regex("[ ,:]"))).writeln' std.regex.Splitter!(cast(Flag)false, string, Regex!char).Splitter That final value is a range type. Consider the guides at the top of https://dlang.org/phobos/std_range.html Ranges take a while to get comfortable with.
Re: rt/aaA.d Line: 553
On Friday, 14 February 2020 at 23:41:45 UTC, Steven Schveighoffer wrote: On 2/14/20 6:36 PM, Ferhat Kurtulmuş wrote: İf ((aa.used + 1)* GROW_DEN > aa.dim * GROW_NUM) aa.grow(ti.key); This call is expensive (it reallocates all the buckets and reinserts all the existing data into the new bucket), it should be avoided if in the end we will not be incrementing used. -Steve I am trying to write a gc-free AA based on the original runtime code (mem with malloc and free). My question is that why my version is slower (about 1.5 times slower) than the runtime version? https://controlc.com/2e58c305 Those are some differences from runtime version: - nogc and no typeid of course. - does not care about postblit of key types (don't need it, assume only basic types are allowed for key type) - runtime version uses typeid to do some alignments which are not implemented in my version. Is that the reason why my code is slower?
Re: static foreach over enum symbols
On Friday, 14 February 2020 at 22:24:14 UTC, Ben Jones wrote: Hi all, I'm getting unexpected results while trying to process symbols from a module, some of which are enums. Depending on whether or not I comment out the first static foreach loop below, fullyQualifiedName gives me different results in the second loop. In either case, I'm surprised I can't grab the UDAs in the second static foreach loop. Any ideas what's going on? Test case: ---a.d--- module a; @Object enum x = "hello"; @Object enum y = "goodbye"; @Object struct z{} ---main.d--- template symbols(alias Mod){ import std.meta; alias toSymbol(alias T) = __traits(getMember, Mod, T); alias symbols = staticMap!(toSymbol, __traits(allMembers, Mod)); } void main(){ import std.traits; import std.meta; import a; //commenting this out changes the results below static foreach(sym; symbols!a){ pragma(msg, fullyQualifiedName!sym); pragma(msg, __traits(getAttributes, sym)); } pragma(msg, "\nget with UDAs\n"); pragma(msg, getSymbolsByUDA!(a, Object)); alias udaSyms = getSymbolsByUDA!(a, Object); pragma(msg, staticMap!(fullyQualifiedName, udaSyms)); static foreach(us; udaSyms){ pragma(msg, fullyQualifiedName!us); pragma(msg, __traits(getAttributes, us)); } } --- annotated output of dmd main.d: with the first loop commented out: get with UDAs tuple("hello", "goodbye", (z)) tuple("a.x", "a.y", "a.z") a.x tuple() //why is the UDA gone? a.y tuple() a.z tuple((Object)) and with the first loop: object tuple() main.main.sym //it's not a.x anymore, it's the name of the local var for static foreach? tuple() main.main.sym tuple() a.z tuple((Object)) get with UDAs tuple("hello", "goodbye", (z)) tuple("main.main.sym", "main.main.sym", "a.z") //and the results are changed here too? main.main.sym tuple() main.main.sym tuple() a.z tuple((Object)) From language spec [1]: "the name of the static foreach variable is bound to the i-th entry of the sequence, either as an enum variable declaration (for constants) or an alias declaration (for symbols). Enums are treated differently, so your 'sym' is not an alias to the original enum but an enum itself with the same value. Because of that, fullyQualifiedName or any template with alias argument will just get the sym temporary not the enum from the symbols tuple. This code should work: static foreach(i, _; symbols!a){ pragma(msg, fullyQualifiedName!(symbols!a[i])); // or manually aliased, but you need to use regular foreach or {{ }} to avoid redefinitions. alias sym = symbols!a[i]; pragma(msg, fullyQualifiedName!sym); } [1] https://dlang.org/spec/version.html#staticforeach
Re: static foreach over enum symbols
On Friday, 14 February 2020 at 22:24:14 UTC, Ben Jones wrote: Hi all, I'm getting unexpected results while trying to process symbols from a module, some of which are enums. Depending on whether or not I comment out the first static foreach loop below, fullyQualifiedName gives me different results in the second loop. Looking more in detail it seems there is another peculiarity happening here, it could be that a template instance get reused (issue 14501). Not sure if it's really a bug or by design. https://issues.dlang.org/show_bug.cgi?id=14501
Re: Difference between range `save` and copy constructor
On 2/15/20 5:53 AM, uranuz wrote: I am interested in current circumstances when we have new copy constructor feature what is the purpose of having range `save` primitive? For me they look like doing basicaly the same thing. And when looking in some source code of `range` module the most common thing that `save` does is that it use constructor typeof(this) to create a new instance and use `save` on the source range: https://github.com/dlang/phobos/blob/v2.090.1/std/range/package.d So what is conceptual difference between `save` and copy contructor of range? Nothing. IMO, any time you are doing anything in save other than `return this;`, you shouldn't have implemented it. The original impetus for the save requirement was so that forward ranges could have a tangible checkable thing that allows introspection (does the range have a save method?). I'm not entirely sure if disabled postblit was even available at the time. The correct way to do it would be to treat ranges that can be copied (regardless of whether they have a copy constructor) as forward ranges, and treat ones that cannot be copied as input ranges. But it's hard to redo ranges like this with all existing code out there. -Steve
Re: rt/aaA.d Line: 553
On 2/15/20 6:49 AM, Ferhat Kurtulmuş wrote: On Friday, 14 February 2020 at 23:41:45 UTC, Steven Schveighoffer wrote: On 2/14/20 6:36 PM, Ferhat Kurtulmuş wrote: İf ((aa.used + 1)* GROW_DEN > aa.dim * GROW_NUM) aa.grow(ti.key); This call is expensive (it reallocates all the buckets and reinserts all the existing data into the new bucket), it should be avoided if in the end we will not be incrementing used. I am trying to write a gc-free AA based on the original runtime code (mem with malloc and free). My question is that why my version is slower (about 1.5 times slower) than the runtime version? Have you ensured you are using -inline, -O, and -release? This is how druntime is compiled. https://controlc.com/2e58c305 Those are some differences from runtime version: - nogc and no typeid of course. - does not care about postblit of key types (don't need it, assume only basic types are allowed for key type) Postblit should be automatic for your code because you are doing the types directly. - runtime version uses typeid to do some alignments which are not implemented in my version. Is that the reason why my code is slower? No, alignments are important only if you don't have the type, which you do. The runtime uses void pointers and opaque structs, so it has to duplicate what the compiler is already doing for you. Your code looks like a direct port, except for the allocations, so it should be as fast if compiled the same. Your code might even be faster, because it's going to be able to inline more aggressively. There may be issues with cache coherency, but I'm not sure how to find or diagnoce those. I'll note that you are going to leak some memory because you are not freeing deleted buckets when you resize. In the GC version, the GC takes care of those. -Steve
Re: How the hell to split multiple delims?
On 2/15/20 6:32 AM, AlphaPurned wrote: I've tried 10 different ways with split and splitter, I've used all the stuff that people have said online but nothing works. I always get a template mismatch error. Why is something so easy to do so hard in D? auto toks = std.regex.split(l, Regex("s")); auto toks = std.regex.splitter(l, Regex("s")); auto toks = std.regex.splitter(l, ctRegex!r"\."); What type is 'l'? -Steve
Re: Difference between range `save` and copy constructor
On Saturday, February 15, 2020 7:34:42 AM MST Steven Schveighoffer via Digitalmars-d-learn wrote: > On 2/15/20 5:53 AM, uranuz wrote: > > I am interested in current circumstances when we have new copy > > constructor feature what is the purpose of having range `save` > > primitive? For me they look like doing basicaly the same thing. And when > > looking in some source code of `range` module the most common thing that > > `save` does is that it use constructor typeof(this) to create a new > > instance and use `save` on the source range: > > https://github.com/dlang/phobos/blob/v2.090.1/std/range/package.d > > > > So what is conceptual difference between `save` and copy contructor of > > range? > > Nothing. IMO, any time you are doing anything in save other than `return > this;`, you shouldn't have implemented it. > > The original impetus for the save requirement was so that forward ranges > could have a tangible checkable thing that allows introspection (does > the range have a save method?). > > I'm not entirely sure if disabled postblit was even available at the time. > > The correct way to do it would be to treat ranges that can be copied > (regardless of whether they have a copy constructor) as forward ranges, > and treat ones that cannot be copied as input ranges. > > But it's hard to redo ranges like this with all existing code out there. Actually, as I understand it, the main reason that save was introduced was so that classes could be forward ranges. While it would be possible to use the postblit constructor or copy constructor with structs, that obviously won't work for classes - hence when save is required. Personally, I think that we'd be better of simply requiring that forward rangse be copyable and force classes that want to be forward ranges to be wrapped by structs, but that would require reworking the range API, and it's far from a trivial change. In practice though, classes should almost never be used as forward ranges, because calling save on them would requires allocating a now object, and that gets expensive fast. As part of testing dxml, I tested it with forward ranges that were classes in order to make sure that they were handled correctly, and their performance was absolutely terrible in comparison to ranges that were structs or strings. - Jonathan M Davis
Re: Difference between range `save` and copy constructor
On 2/15/20 9:45 AM, Jonathan M Davis wrote: On Saturday, February 15, 2020 7:34:42 AM MST Steven Schveighoffer via Digitalmars-d-learn wrote: On 2/15/20 5:53 AM, uranuz wrote: I am interested in current circumstances when we have new copy constructor feature what is the purpose of having range `save` primitive? For me they look like doing basicaly the same thing. And when looking in some source code of `range` module the most common thing that `save` does is that it use constructor typeof(this) to create a new instance and use `save` on the source range: https://github.com/dlang/phobos/blob/v2.090.1/std/range/package.d So what is conceptual difference between `save` and copy contructor of range? Nothing. IMO, any time you are doing anything in save other than `return this;`, you shouldn't have implemented it. The original impetus for the save requirement was so that forward ranges could have a tangible checkable thing that allows introspection (does the range have a save method?). I'm not entirely sure if disabled postblit was even available at the time. The correct way to do it would be to treat ranges that can be copied (regardless of whether they have a copy constructor) as forward ranges, and treat ones that cannot be copied as input ranges. But it's hard to redo ranges like this with all existing code out there. Actually, as I understand it, the main reason that save was introduced was so that classes could be forward ranges. While it would be possible to use the postblit constructor or copy constructor with structs, that obviously won't work for classes - hence when save is required. I remember the discussions as being about how an actual implementation detail was required, not just a mark. I remember a suggestion for just putting an enum isForward member in the range being rejected because of this. Except people don't call save. They just copy, and it works for nearly all forward ranges in existence. And a class allocating a new class for saving a forward range is a mislabeled "cheap" operation IMO. Personally, I think that we'd be better of simply requiring that forward rangse be copyable and force classes that want to be forward ranges to be wrapped by structs, but that would require reworking the range API, and it's far from a trivial change. Yep. In practice though, classes should almost never be used as forward ranges, because calling save on them would requires allocating a now object, and that gets expensive fast. As part of testing dxml, I tested it with forward ranges that were classes in order to make sure that they were handled correctly, and their performance was absolutely terrible in comparison to ranges that were structs or strings. Not surprised ;) -Steve
Re: rt/aaA.d Line: 553
On Saturday, 15 February 2020 at 14:30:20 UTC, Steven Schveighoffer wrote: On 2/15/20 6:49 AM, Ferhat Kurtulmuş wrote: On Friday, 14 February 2020 at 23:41:45 UTC, Steven I'll note that you are going to leak some memory because you are not freeing deleted buckets when you resize. In the GC version, the GC takes care of those. -Steve I appreciate it for reviewing the code and your comments. Speed is good now. I put it on the dub db. I hope I am not violating any copyright. I included name of the original author (Martin Nowak) in the code, and explicitly stated that "betterC port of druntime/blob/master/src/rt/aaA.d". What do you think about this one? I am not free-ing deleted entry in remove method: https://github.com/aferust/bcaa/blob/a37b4ee4455477abc82425f32e9cf45394f4c4a1/source/bcaa.d#L228-L230 but here in resize: https://github.com/aferust/bcaa/blob/a37b4ee4455477abc82425f32e9cf45394f4c4a1/source/bcaa.d#L190-L194 Thus, deleted buckets will wait until a resize call to free them. I think this is better for speed.
Re: How to get to body of HTTP 500 error with std.net.curl.get()?
On Friday, 14 February 2020 at 13:23:01 UTC, Andre Pany wrote: On Friday, 14 February 2020 at 00:24:27 UTC, Gregor Mückl wrote: Hi! I am trying to write a client for pretty... well... creatively designed web API. The server gives HTTP status 500 replies if the requests are malformed, but the actual error message is hidden in the body of the reply (an XML document!). std.net.curl.get() throws an exception in this case. But I would like to get the body to process the error message within. How can I do that? Thanks in advance, Gregor Hi Gregor, If I am not completely wrong, the exception has an attribute "msg" which should contain the body of the http response. Kind regards André Unfortunately, this is not true. The msg only contains the text information in the status line of the HTTP reply. If I'm not mistaken, the exception is created in this line in std/net/curl.d: enforce(statusLine.code / 100 == 2, new HTTPStatusException(statusLine.code, format("HTTP request returned status code %d (%s)", statusLine.code, statusLine.reason))); If anything is wrong, the server I'm interested in tends to reply with a status code 500 and a generic status line text and a bloated XML body containing the actual error message.
Re: rt/aaA.d Line: 553
On Saturday, 15 February 2020 at 15:21:08 UTC, Ferhat Kurtulmuş wrote: On Saturday, 15 February 2020 at 14:30:20 UTC, Steven Schveighoffer wrote: On 2/15/20 6:49 AM, Ferhat Kurtulmuş wrote: On Friday, 14 February 2020 at 23:41:45 UTC, Steven Ops I ve made commits. Here are the links up to date https://github.com/aferust/bcaa/blob/3f0f4eaf550a28b80cd95a4f2589b1f3a53fe6c0/source/bcaa.d#L193-L195 https://github.com/aferust/bcaa/blob/3f0f4eaf550a28b80cd95a4f2589b1f3a53fe6c0/source/bcaa.d#L231-L233
Re: Dscanner: is it possible to switch off style checks case-by-case?
On Thursday, 13 February 2020 at 17:15:50 UTC, mark wrote: I'm starting out with GtkD and have this function: void main(string[] args) { Main.init(args); auto game = new GameWindow(); Main.run(); } and this method: void quit(Widget widget) { Main.quit(); } When I run dscanner --styleCheck it reports: ./src/app.d(10:10)[warn]: Variable game is never used. ./src/app.d(22:22)[warn]: Parameter widget is never used. These are correct. However, is it possible to switch them off individually? (In Python you can switch off lint checks using a special text in a comment at the end of the line.) With DLS, you can use @suppress in comment: void quit(Widget widget) // @suppress(dscanner.suspicious.unused_parameter) { Main.quit(); } more info: https://code.dlang.org/packages/dls Simply install the extension to your editor.
Re: How to get to body of HTTP 500 error with std.net.curl.get()?
On Saturday, 15 February 2020 at 16:25:42 UTC, Gregor Mückl wrote: Unfortunately, this is not true. The msg only contains the text information in the status line of the HTTP reply. If I'm not mistaken, the exception is created in this line in std/net/curl.d: enforce(statusLine.code / 100 == 2, new HTTPStatusException(statusLine.code, format("HTTP request returned status code %d (%s)", statusLine.code, statusLine.reason))); If anything is wrong, the server I'm interested in tends to reply with a status code 500 and a generic status line text and a bloated XML body containing the actual error message. Not that it answers your question but requests[1] can do this, if you don't mind adding some dependencies. Request req; Response res = req.get(urlRespondingWith500); assert(res.code == 500); writeln(res.responseBody); // Buffer!ubyte; use .to!string to get a string When testing to confirm I ran into a bug[2] where the body is sometimes empty, but outside of fringe cases it should work. [1]: https://code.dlang.org/packages/requests [2]: https://github.com/ikod/dlang-requests/issues/115
Re: How to get to body of HTTP 500 error with std.net.curl.get()?
On Friday, 14 February 2020 at 00:24:27 UTC, Gregor Mückl wrote: Hi! I am trying to write a client for pretty... well... creatively designed web API. The server gives HTTP status 500 replies if the requests are malformed, but the actual error message is hidden in the body of the reply (an XML document!). std.net.curl.get() throws an exception in this case. But I would like to get the body to process the error message within. How can I do that? Thanks in advance, Gregor It seems you can't, that simple get wrapper is very limited. Better create you own get function, example: import std; ushort get(string url, ref ubyte[] content) { auto cont = appender(&content); auto http = HTTP(); http.method = HTTP.Method.get; http.url = url; http.onReceive = (ubyte[] data) { cont ~= data; return data.length; }; HTTP.StatusLine status; http.onReceiveStatusLine = (HTTP.StatusLine s) { status = s; }; http.perform(); return status.code; } void main() { ubyte[] data; auto scode = get("http://dlang.org/asdf";, data); if (scode == 404) { // data has the body ... }
Re: How the hell to split multiple delims?
On Saturday, 15 February 2020 at 11:32:42 UTC, AlphaPurned wrote: I've tried 10 different ways with split and splitter, I've used all the stuff that people have said online but nothing works. I always get a template mismatch error. Why is something so easy to do so hard in D? auto toks = std.regex.split(l, Regex("s")); auto toks = std.regex.splitter(l, Regex("s")); auto toks = std.regex.splitter(l, ctRegex!r"\."); I had the same problem myself recently, and almost ended up here to ask the same question as you but stumbled across the following (ugly) solution without using regexs. char[] line = "Split this by#space or#sign." auto parts = line.splitter!(a => a=='#' | a==' ').array;
Re: How the hell to split multiple delims?
On Saturday, 15 February 2020 at 22:30:03 UTC, Craig Dillabaugh wrote: On Saturday, 15 February 2020 at 11:32:42 UTC, AlphaPurned wrote: I've tried 10 different ways with split and splitter, I've used all the stuff that people have said online but nothing works. I always get a template mismatch error. Why is something so easy to do so hard in D? auto toks = std.regex.split(l, Regex("s")); auto toks = std.regex.splitter(l, Regex("s")); auto toks = std.regex.splitter(l, ctRegex!r"\."); I had the same problem myself recently, and almost ended up here to ask the same question as you but stumbled across the following (ugly) solution without using regexs. char[] line = "Split this by#space or#sign." auto parts = line.splitter!(a => a=='#' | a==' ').array; This works for me: import std; void main() { string line = "Split this by#space or#sign."; auto parts = line.splitter(regex("[ #]")).array; writeln(parts); // ["Split", "this", "by", "space", "or", "sign."] }
Re: rt/aaA.d Line: 553
On 2/15/20 10:21 AM, Ferhat Kurtulmuş wrote: On Saturday, 15 February 2020 at 14:30:20 UTC, Steven Schveighoffer wrote: On 2/15/20 6:49 AM, Ferhat Kurtulmuş wrote: On Friday, 14 February 2020 at 23:41:45 UTC, Steven I'll note that you are going to leak some memory because you are not freeing deleted buckets when you resize. In the GC version, the GC takes care of those. I appreciate it for reviewing the code and your comments. Speed is good now. I put it on the dub db. I hope I am not violating any copyright. I included name of the original author (Martin Nowak) in the code, and explicitly stated that "betterC port of druntime/blob/master/src/rt/aaA.d". What do you think about this one? I am not free-ing deleted entry in remove method: https://github.com/aferust/bcaa/blob/a37b4ee4455477abc82425f32e9cf45394f4c4a1/source/bcaa.d#L228-L230 but here in resize: https://github.com/aferust/bcaa/blob/a37b4ee4455477abc82425f32e9cf45394f4c4a1/source/bcaa.d#L190-L194 Yes, that is the moment they truly become garbage (in the GC version), so it's where you should free them. -Steve