Re: questions around mutating range algorithms, const, and return ref
On 01/28/2018 02:52 PM, aliak wrote: > Hello, I'm trying to write a function called "pull" that, given 2 > ranges, "pull"s the values from range 2 out of range 1. I'm not sure if > I'm doing it correctly though, and I have some questions so any help is > appreciated. This is what I have: > > ref pull(R1, R2)(return ref R1 r1, R2 r2) { > import std.algorithm, std.array, std.range; > int numFound = 0; > auto r = r1.save; > ElementType!R1[] unfoundElements; > foreach (e; r) { > if (!r2.canFind(e)) { > unfoundElements ~= e; > } else { > numFound++; > } > } > moveEmplaceAll(unfoundElements, r1); > r1.popBackN(numFound); > return r1; > } > > So my questions are: > > 1) So first of all, is there a function like this in phobos that I can > use? From what I understand phobos is supposed to be nogc so mutating > functions like these are usually in place ones? I think the following trivial wrapper around std.algorithm.remove() should do: void removeMatching(R, N)(ref R r, N needles) { import std.algorithm : remove, canFind; r = r.remove!(e => needles.canFind(e)); } void main() { auto arr = [1, 2, 3, 2, 4]; arr.removeMatching([2, 3]); assert(arr == [1, 4]); } > 2) Is there a way to avoid the extra "moveEmplaceAll" call towards the > end and still get the same results? I'm not convinced that unfoundElements is needed at all. :) > 3) Is it necessary to always import std.array (or std.range: empty, > front) when doing work like this with range algorithms? (otherwise you > get no property save when an array is used as a range) I think importing std.range works as well. > 6) It will not work when I pass in a range that has const elements. > > ie: > > const(int)[] arr = [1, 2, 3, 4, 5]; > arr.pull([2, 3]); > > This I guess makes sense because moveEmplaceAll depends on isInputRange > and from my understanding, a const range cannot be one (is that > correct?). Yes but your range is not const, the elements are. So, although const(int)[] is a range, it does not have mutable elements. > So am I correct in thinking there really is no way around > this, or is there some move/cast trickery that I can use maybe? You don't want to mutate const elements anyway. It would be breaking a promise that other parts of the program may be depending on. I would return a filtered-out range: import std.algorithm; void main() { const(int)[] arr = [1, 2, 3, 2, 4]; auto result = arr.filter!(e => ![2, 3].canFind(e)); assert(result.equal([1, 4])); } If needed, the caller can easily make an array out of the filtered range and the element types will still be const(int): import std.range; auto arr2 = result.array(); static assert(is(typeof(arr2) == const(int)[])); > > Cheers, > - Ali Ali
Re: parallelism
On Sunday, 28 January 2018 at 04:44:23 UTC, thedeemon wrote: On Saturday, 27 January 2018 at 20:49:43 UTC, Arun Chandrasekaran wrote: But really I'm not sure why you want static foreach here I was just trying to see if static foreach can be used here, but well, you showed that it's not required. I just got intrigued to see the error on labeled break. Thanks anyway.
Re: enforce (i > 0) for i = int.min does not throw
On Sunday, 28 January 2018 at 19:17:49 UTC, Steven Schveighoffer wrote: On 1/27/18 9:50 AM, ag0aep6g wrote: Wow, that looks really bad. Apparently, dmd implements `i < 0` as a `i >> 31`. I.e., it shifts the bits to the right so far that only the sign bit is left. This is ok. But it implements `i > 0` as `(-i) >> 31`. That would be correct if negation would always flip the sign bit. But it doesn't for `int.min`. `-int.min` is `int.min` again. So dmd emits wrong code for `i > 0`. O_O I've filed an issue: https://issues.dlang.org/show_bug.cgi?id=18315 This is insane. i > 0 is used in so many places. The only saving grace appears to be that int.min is just so uncommonly seen in the wild. I tested all the way back to 2.040, still has the same behavior. -Steve FYI/OT: If you need to check the behavior of old compilers, the "All" option at run.dlang.io might be helpful. It starts from 2.060 and it works best for consistent output (i.e. without stacktrace pointer). Examples: - https://run.dlang.io/is/IoN3sj (code from the bug report) - https://run.dlang.io/is/LuxUQ5 (code from the bug report, slightly modified) - https://run.dlang.io/is/3R4r1U (simple example of "when was the symbol added to Phobos?") (It's based on Vladimir's regression tester and can be used locally too: https://github.com/dlang-tour/core-dreg)
Re: Looks like wrong error message
On Sunday, January 28, 2018 16:08:17 H. S. Teoh via Digitalmars-d-learn wrote: > On Sun, Jan 28, 2018 at 10:53:39PM +, welkam via Digitalmars-d-learn wrote: > > On Sunday, 28 January 2018 at 20:42:52 UTC, Jonathan M Davis wrote: > [...] > > > > However, you're not going to get an error message that says anything > > > like "the arguments aren't the same type." The compiler doesn't > > > understand what the template constraint means in "human terms." It > > > just knows whether it's true or false, and in this case, if you > > > provide arguments that don't have a common type that they implicitly > > > convert to, then the template constraint will fail. But ultimately, > > > you're going to have to read the template constraint and figure out > > > why the arguments are failing. > > [...] > > Well, that's not *quite* true. The compiler *does* have enough > information to be able evaluate the constraints, for one. So in theory > it *should* be able to identify which constraint(s) failed. Some time > ago there was a push to refactor Phobos sig constraints in CNF > (conjunctive normal form), which would simplify this somewhat: if a > function has sig constraints X, Y and Z, and Y evaluated to false, then > the compiler could print condition Y as the cause of failure. Sure, work could be done to indicate which pieces of a template constraint are true and which are false, but the point still stands that it can't actually tell the programmer what that means in "human terms." The intent isn't there. Now, that's why there have been suggestions for doing stuff like providing error strings to go with template constraints that can be displayed on failure, but ultimately, the compiler can't read the programmer's mind. > Of course, even in spite of this, displaying the failed conditions is > still better than nothing. If the compiler assumes CNF on sig > constraints, then it can list, along with each candidate overload, the > failing term(s) in the CNF for that particular overload as the reason > that overload wasn't chosen. IMHO, that's doomed to failure unless the compiler somehow requires that the template constraints be in CNF, which would be really annoying in its own right. The most practical thing at this point is to intelligently use traits with useful names in template constraints and to simplify the constraints as much as possible, with the overloading primarily done internally with static ifs - like you like to point out, and we've done some of that to Phobos, but there's a lot of work left to be done there. Still, I think that it's always going to be the case on some level that the programmer is going to have to look at template constraints and figure out why they're failing, even if we do manage to improve how much information is given about which parts are failing. - Jonathan M Davis
Re: Looks like wrong error message
On Sun, Jan 28, 2018 at 10:53:39PM +, welkam via Digitalmars-d-learn wrote: > On Sunday, 28 January 2018 at 20:42:52 UTC, Jonathan M Davis wrote: [...] > > However, you're not going to get an error message that says anything > > like "the arguments aren't the same type." The compiler doesn't > > understand what the template constraint means in "human terms." It > > just knows whether it's true or false, and in this case, if you > > provide arguments that don't have a common type that they implicitly > > convert to, then the template constraint will fail. But ultimately, > > you're going to have to read the template constraint and figure out > > why the arguments are failing. [...] Well, that's not *quite* true. The compiler *does* have enough information to be able evaluate the constraints, for one. So in theory it *should* be able to identify which constraint(s) failed. Some time ago there was a push to refactor Phobos sig constraints in CNF (conjunctive normal form), which would simplify this somewhat: if a function has sig constraints X, Y and Z, and Y evaluated to false, then the compiler could print condition Y as the cause of failure. Furthermore, the reason for the perceived unhelpful message is more subtle. It's because a sig constraint amounts to a limitation in scope of a particular overload, effectively saying "this overload only applies if conditions X, Y and Z are true". So a failure in one or more sig constraints isn't necessarily a *problem* per se; it just means that particular overload declines instantiation to the rest of the overload set. Only if the failure ultimately leads to a failure to match *all* overloads, can we say for sure that the failed constraint was the "cause" of the mismatch. And this is where things get tricky, because if you have an overload of, say, 10 members, then obviously a failure to find a match means that *every* overload had its sig constraints fail one way or another. But without being able to read the programmer's mind, the compiler has no idea which overload was the *intended* target of the function call; so it would not be able to tell which failed sig constraint was the most relevant to the user. All >=10 failed conditions would have to be displayed, and it would be up to the user to decide which one is the relevant one. Of course, even in spite of this, displaying the failed conditions is still better than nothing. If the compiler assumes CNF on sig constraints, then it can list, along with each candidate overload, the failing term(s) in the CNF for that particular overload as the reason that overload wasn't chosen. For example, the output could be something like: Error: unable to match func() with argument type X; candidates are: std/range/package.d(100): auto func(R)(R r) if (isInputRange!R && is(ElementType!R == char): condition is(ElementType!R == char) failed std/range/package.d(200: auto func(R)(R r) if (isForwardRange!R && is(ElementType!R : int): condition isForwardRange!R failed std/range/package.d(300): auto func(E)(E[] arr): X does not match parameter type E[] You'd still have to parse through each listed overload, but at least the compiler would tell you which sig constraint failed. IME, this would be helpful, because sometimes it's not at all obvious which sig constraint failed, especially if the sig constraints call upon other templates to test the incoming type (e.g., isInputRange, which contains a whole bunch of tests, any of which could fail and it's not always obvious which ones), and I wind up having to parse through *all* sig constraints of *all* overloads just to figure out which one was the real cause. > I would not complain if there were multiple functions just like error > said. But the set contains only one making it not a set anymore and > it says nothing about constraints. [...] This topic has come up again numerous times, and I think *some* improvement on this front is necessary. One improvement is to decrease our reliance on overloads, and to use more permissive sig constraints with static ifs inside the function body that can provide a more helpful error message. Not to mention, some of the current Phobos overloads are divided based on implementation details user code shouldn't need to know about, rather than *logical* overload boundaries, for example: // handle the case when S is a string auto func(R,S)(R haystack, S needle) if (isInputRange!R && isSomeString!S) ... // handle the case when S is an array but not a string auto func(R,S)(R haystack, S needle) if (isInputRange!R && !isSomeString!S && isArray!S) ... This is leaking implementation details into the sig constraints; it really should be written this way instead: auto func(R,S)(R haystack, S needle) if (isInputRange!R) { static if (isSomeString!S) ... // handle
Re: Looks like wrong error message
On Sunday, 28 January 2018 at 20:42:52 UTC, Jonathan M Davis wrote: There is nothing incorrect about the error message. The compiler looked at all of the functions in the overload set, and it found none that matched. The reason that it found none that matched was because it couldn't find any function template where those arguments passed the template constraint, and it tells you so. So, there is no bug here in the sense that the compiler is telling you the wrong thing. You can certainly open a bug report arguing that the error messages isn't human-friendly enough and suggest alternatives, and something along those lines may be implemented, but the message isn't actually wrong. So, feel free to open a bug report. However, you're not going to get an error message that says anything like "the arguments aren't the same type." The compiler doesn't understand what the template constraint means in "human terms." It just knows whether it's true or false, and in this case, if you provide arguments that don't have a common type that they implicitly convert to, then the template constraint will fail. But ultimately, you're going to have to read the template constraint and figure out why the arguments are failing. - Jonathan M Davis I would not complain if there were multiple functions just like error said. But the set contains only one making it not a set anymore and it says nothing about constraints. I downloaded dmd source. Might figure out something myself tomorrow
questions around mutating range algorithms, const, and return ref
Hello, I'm trying to write a function called "pull" that, given 2 ranges, "pull"s the values from range 2 out of range 1. I'm not sure if I'm doing it correctly though, and I have some questions so any help is appreciated. This is what I have: ref pull(R1, R2)(return ref R1 r1, R2 r2) { import std.algorithm, std.array, std.range; int numFound = 0; auto r = r1.save; ElementType!R1[] unfoundElements; foreach (e; r) { if (!r2.canFind(e)) { unfoundElements ~= e; } else { numFound++; } } moveEmplaceAll(unfoundElements, r1); r1.popBackN(numFound); return r1; } So my questions are: 1) So first of all, is there a function like this in phobos that I can use? From what I understand phobos is supposed to be nogc so mutating functions like these are usually in place ones? 2) Is there a way to avoid the extra "moveEmplaceAll" call towards the end and still get the same results? 3) Is it necessary to always import std.array (or std.range: empty, front) when doing work like this with range algorithms? (otherwise you get no property save when an array is used as a range) 4) is the .save necessary? My (initial) tests seem to show that it works without, but from my understanding of what save does, it feels like it's necessary. 5) return ref and -dip25 ... is that something that's going to become default at some time? Is there a timeline? (also curious about dip1000 for that matter). 6) It will not work when I pass in a range that has const elements. ie: const(int)[] arr = [1, 2, 3, 4, 5]; arr.pull([2, 3]); This I guess makes sense because moveEmplaceAll depends on isInputRange and from my understanding, a const range cannot be one (is that correct?). So am I correct in thinking there really is no way around this, or is there some move/cast trickery that I can use maybe? Cheers, - Ali
Re: rdmd main.d leads to Segmentation fault
On Saturday, 27 January 2018 at 21:04:07 UTC, Kagamin wrote: On Friday, 26 January 2018 at 22:40:29 UTC, Timoses wrote: Program received signal SIGSEGV, Segmentation fault. 0x00432e04 in _d_dso_registry () (gdb) bt #0 0x00432e04 in _d_dso_registry () #1 0x00431c63 in ?? () #2 0x0045c08b in __libc_csu_init () #3 0xb7d8e206 in __libc_start_main (main=0x431c24 , argc=1, argv=0xb784, init=0x45c040 <__libc_csu_init>, fini=0x45c0a0 <__libc_csu_fini>, rtld_fini=0xb7feb080 <_dl_fini>, stack_end=0xb77c) at ../csu/libc-start.c:247 #4 0x004315c1 in _start () Any ideas? What `disas` command shows at the point of failure? How would I do that? $ (gdb) info line main No line number information available for address 0x431c24 $ (gdb) info line 0x431c24 Function "0x431c24" not defined. ?
Re: rdmd main.d leads to Segmentation fault
On Saturday, 27 January 2018 at 01:23:44 UTC, Fra Mecca wrote: On Friday, 26 January 2018 at 22:40:29 UTC, Timoses wrote: Hey, simple hello world crashes with segfault: [...] Where did you get the D toolchain? Got it from here: http://d-apt.sourceforge.net/ with $ apt-get install dmd-compiler Does the same segmentation fault happen with dmd or gdc or ldc? (dmd should be the more probable) dmd: generated executable also leads to segfault gdc: works... ldc: didn't try $ gdc --version gdc (Debian 6.3.0-18) 6.3.0 20170516 Can you compile a dub project? No, leads to executable causing a segfault as well So, it does compile, but compiled executable with dmd seems to cause segfault.
Re: assert and enforce both compiled out with -release
On 01/28/2018 11:31 AM, Steven Schveighoffer wrote: >> Fixed it through the "Improve this page" link on that Phobos page: >> >>https://github.com/dlang/phobos/blob/master/std/exception.d >> >> Ali > > Hm... it appears that you committed directly to the branch. Even if > changing docs, you should do so with a pull request. > > For normal mortals, this happens automatically, but for people who have > commit rights, you have to be careful to select the right thing ;) > > -Steve Guilty as charged! Seb has already brought me to my senses by email. Ali
Re: Looks like wrong error message
On Sunday, January 28, 2018 20:02:48 welkam via Digitalmars-d-learn wrote: > Error says that it cant deduce function from argument types but > in reality it fails to meet function template constraints. In > this case !is(CommonType!(staticMap!(ElementType, > staticMap!(Unqual, Ranges))) == void) > > In human terms it means that arguments are not the same type. Is > this require bug report or it works as expected? > > Code: > void main() { > import std.range : chain; > string s = "string"; > auto arrayOfStrings = ["string"]; > arrayOfStrings.chain(s); > } > > error: > Main.d(9): Error: template std.range.chain cannot deduce function > from argument types !()(string[], string), candidates are: > C:\D\dmd2\windows\bin\..\..\src\phobos\std\range\package.d(894): >std.range.chain(Ranges...)(Ranges rs) if (Ranges.length > 0 > && allSatisfy!(isInputRange, staticMap!(Unqual, Ranges)) && > !is(CommonType!(staticMap!(ElementType, staticMap!(Unqual, > Ranges))) == void)) There is nothing incorrect about the error message. The compiler looked at all of the functions in the overload set, and it found none that matched. The reason that it found none that matched was because it couldn't find any function template where those arguments passed the template constraint, and it tells you so. So, there is no bug here in the sense that the compiler is telling you the wrong thing. You can certainly open a bug report arguing that the error messages isn't human-friendly enough and suggest alternatives, and something along those lines may be implemented, but the message isn't actually wrong. So, feel free to open a bug report. However, you're not going to get an error message that says anything like "the arguments aren't the same type." The compiler doesn't understand what the template constraint means in "human terms." It just knows whether it's true or false, and in this case, if you provide arguments that don't have a common type that they implicitly convert to, then the template constraint will fail. But ultimately, you're going to have to read the template constraint and figure out why the arguments are failing. - Jonathan M Davis
Looks like wrong error message
Error says that it cant deduce function from argument types but in reality it fails to meet function template constraints. In this case !is(CommonType!(staticMap!(ElementType, staticMap!(Unqual, Ranges))) == void) In human terms it means that arguments are not the same type. Is this require bug report or it works as expected? Code: void main() { import std.range : chain; string s = "string"; auto arrayOfStrings = ["string"]; arrayOfStrings.chain(s); } error: Main.d(9): Error: template std.range.chain cannot deduce function from argument types !()(string[], string), candidates are: C:\D\dmd2\windows\bin\..\..\src\phobos\std\range\package.d(894): std.range.chain(Ranges...)(Ranges rs) if (Ranges.length > 0 && allSatisfy!(isInputRange, staticMap!(Unqual, Ranges)) && !is(CommonType!(staticMap!(ElementType, staticMap!(Unqual, Ranges))) == void))
Re: D generates large assembly for simple function
On Sunday, 28 January 2018 at 14:33:04 UTC, Johan Engelen wrote: Careful with these comparisons guys. Know what you are looking at. Wise words
Re: vibe.d compatible with d3 or pixieJS
On 1/28/18 11:45 AM, Mark wrote: Hello! As the title suggests, I'm looking for the answer to this question. I've searched / asked it on the vibe forums, but nobody has answered. vibe.d is a server, and it serves javascript just fine. I've experimented with vibe, and I would like to build a data visualization website using one of the two (preferably pixieJS). Either is fine AFAIK, javascript is browser-side, so the server just has to dish out the files for the browser to run them. -Steve
Re: assert and enforce both compiled out with -release
On 1/27/18 9:31 AM, Ali Çehreli wrote: On 01/27/2018 05:52 AM, kdevel wrote: > https://dlang.org/phobos/std_exception.html#enforce states: > > | Also, do not use enforce inside of contracts (i.e. inside of in and > out blocks > | and invariants), because they will be compiled out when compiling with > -release. > | Use assert in contracts. > > But assert is also ignored in release mode: The documentation is not clear. "they will be compiled out" means "contracts are compiled out". So, an enforce() would disappear if it's inside such a block, which should not be what the programmer wants for an enforce(). There is another problem with using enforce in contracts, it throws Exceptions, whereas contracts are expected to throw Errors. The most important aspect about this is that nothrow functions can still throw Errors. So if you have a nothrow function with an in-contract that throws an Exception, compiling in release mode may is a mistake (I'm not sure if the compiler even detects this). I think the current docs (as they have been modified) are fine. Fixed it through the "Improve this page" link on that Phobos page: https://github.com/dlang/phobos/blob/master/std/exception.d Ali Hm... it appears that you committed directly to the branch. Even if changing docs, you should do so with a pull request. For normal mortals, this happens automatically, but for people who have commit rights, you have to be careful to select the right thing ;) -Steve
Re: enforce (i > 0) for i = int.min does not throw
On 1/27/18 9:50 AM, ag0aep6g wrote: Wow, that looks really bad. Apparently, dmd implements `i < 0` as a `i >> 31`. I.e., it shifts the bits to the right so far that only the sign bit is left. This is ok. But it implements `i > 0` as `(-i) >> 31`. That would be correct if negation would always flip the sign bit. But it doesn't for `int.min`. `-int.min` is `int.min` again. So dmd emits wrong code for `i > 0`. O_O I've filed an issue: https://issues.dlang.org/show_bug.cgi?id=18315 This is insane. i > 0 is used in so many places. The only saving grace appears to be that int.min is just so uncommonly seen in the wild. I tested all the way back to 2.040, still has the same behavior. -Steve
vibe.d compatible with d3 or pixieJS
Hello! As the title suggests, I'm looking for the answer to this question. I've searched / asked it on the vibe forums, but nobody has answered. I'm not familiar enough with JS frameworks / vibe to really know how this would (not) work together. I've experimented with vibe, and I would like to build a data visualization website using one of the two (preferably pixieJS). If they are not, can anyone point to where I should start to make a custom web kit out of the stuff found on dub? Thanks!
Re: Efficient way to pass struct as parameter
Am Wed, 3 Jan 2018 10:57:13 -0800 schrieb Ali Çehreli: > On 01/03/2018 10:40 AM, Patrick Schluter wrote: > > On Tuesday, 2 January 2018 at 23:27:22 UTC, H. S. Teoh wrote: > >> > >> When it comes to optimization, there are 3 rules: profile, profile, > >> profile. I used to heavily hand-"optimize" my code a lot (I come from > >> a strong C/C++ background -- premature optimization seems to be a > >> common malady among us in that crowd). > > > > That's why I always tell that C++ is premature optimization oriented > > programming, aka as POOP. > > […] > > That's why I like producer functions that return values: > > vector makeInts(some param) { > // ... > } > > And if they can be 'pure', D allows them to be used to initialize > immutable variables as well. Pretty cool! :) > > Ali May I add, this is also optimal performance-wise. The result variable will be allocated on the caller stack and the callee writes directly to it. So even POOPs like me, do it. -- Marco
Re: D generates large assembly for simple function
On 01/27/2018 11:42 AM, Matt wrote: Godbolt link: https://godbolt.org/g/t5S976 Careful with these comparisons guys. Know what you are looking at. Rust does not eliminate setting the framepointer register, and so it looks "bad" [1]. Clang also sets the framepointer for macOS ABI regardless of optimization level. https://godbolt.org/g/eeo81n [1] See https://github.com/rust-lang/rust/pull/47152 -Johan
Re: std_exception.html#enforce: example does not compile
On Saturday, 27 January 2018 at 21:27:44 UTC, kdevel wrote: On Saturday, 27 January 2018 at 20:33:46 UTC, Jonathan M Davis wrote: Shall I file a bug report? Yes. https://issues.dlang.org/show_bug.cgi?id=18319 Thanks. Addressed and already merged: https://github.com/dlang/phobos/pull/6080 https://dlang.org/phobos-prerelease/std_exception.html#enforce
Re: assert and enforce both compiled out with -release
On Sun, 28 Jan 2018 00:59:12 +, lobo wrote: > On Saturday, 27 January 2018 at 22:53:37 UTC, Ali Çehreli wrote: >> On 01/27/2018 10:33 AM, kdevel wrote: >> >>> I suggest the deletion of the sentence "Use assert in contracts." >> >> Done. >> >> Ali > > Wait, no this isn't right, is it? Enforce should not be used in > contracts so the "Use assert in contracts" statement is correct and > should remain. I think the issue here is the OP is getting confused > between assert vs. exception. Without that statement, the documentation is still pretty clear that you shouldn't use enforce in contracts, so removing it won't hurt anything, and does make things clearer by staying on-topic.