Re: Comparing two AliasSeq
On Saturday, 25 March 2017 at 05:20:44 UTC, Jonathan M Davis wrote: On Saturday, March 25, 2017 04:57:26 Yuxuan Shui via Digitalmars-d-learn wrote: [...] An AliasSeq isn't really ever a type. AliasSeq!(int, float) is a list of types, not a type itself, and is expressions supports comparing those in at least some instances, because is expressions operate on types, and having them support a list of types is useful. Calling AliasSeq!(int, float) a type would be like claiming that the (int, float) in foo!(int, float) a type. It's a list - a list of template arguments in this case - but it's still a list and not itself a type. [...] Because I want to make use of the "static foreach unrolling" feature (I don't know what's the official name). [...]
Re: Beta 2.074.0-b1
On 25/03/2017 6:33 AM, Jack Stouffer wrote: On Saturday, 25 March 2017 at 05:19:32 UTC, rikki cattermole wrote: On 24/03/2017 6:35 PM, Martin Nowak wrote: First beta for the 2.074.0 release. This release comes with plenty of phobos additions and a new std.experimental module. http://dlang.org/download.html#dmd_beta http://dlang.org/changelog/2.074.0.html Please report any bugs at https://issues.dlang.org -Martin That "new" module isn't documented on the changelog. https://dlang.org/changelog/2.074.0.html#std-experimental-checkedint Okay in that case, std.experimental.checkedint should be in the description "New: Checked, a lightweight and highly configurable checked integral" since I did search for it.
Re: Beta 2.074.0-b1
On Saturday, 25 March 2017 at 05:19:32 UTC, rikki cattermole wrote: On 24/03/2017 6:35 PM, Martin Nowak wrote: First beta for the 2.074.0 release. This release comes with plenty of phobos additions and a new std.experimental module. http://dlang.org/download.html#dmd_beta http://dlang.org/changelog/2.074.0.html Please report any bugs at https://issues.dlang.org -Martin That "new" module isn't documented on the changelog. https://dlang.org/changelog/2.074.0.html#std-experimental-checkedint
Re: Comparing two AliasSeq
On Saturday, March 25, 2017 04:57:26 Yuxuan Shui via Digitalmars-d-learn wrote: > I see. I always thought tuple() is a type... > > So a tuple of types is a type, but a tuple of mixed types and > values is not a type. Doesn't seem very consistent. An AliasSeq isn't really ever a type. AliasSeq!(int, float) is a list of types, not a type itself, and is expressions supports comparing those in at least some instances, because is expressions operate on types, and having them support a list of types is useful. Calling AliasSeq!(int, float) a type would be like claiming that the (int, float) in foo!(int, float) a type. It's a list - a list of template arguments in this case - but it's still a list and not itself a type. An AliaSeq (or tuple as the compiler incorrectly calls it) is essentially a list of symbols or expressions - or aliases - which is why TypeTuple got renamed to AliasSeq; it's not really a tuple (since unlike a tuple, it always expands and is not nestable), and it doesn't hold just types. Also, it's used for template parameters, template arguments, function parameters, and function arguments, so you can't really call it a list of parameters or arguments. So, so it's sort of a list or sequence of aliases, that's what it got changed to - AliasSeq. But that's still not a great name for it. It can just hold too many different things and be used in too many different ways. Essentially though, an AliasSeq is a list of template/function parameters/arguments that happens to be separated from any templates or functions at the moment. In any case, since is expressions are entirely meant for operating on types, having them not work with an AliaSeq that includes values makes sense. In general, mixing types and values in a single AliasSeq isn't a great idea - (though sometimes that's exactly what's required for template arguments). So, code that mixes them is not the norm. > Here is the solution I will go with: > > struct test(T...) { } > import std.range; > static assert (is(test!(expandRange!(iota(0,5))) == test!(0, 1, > 2, 3, 4))); Why are you using is expressons at all? Why are you creating a type? You're dealing purely with values here. As such, why aren't you just using arrays or ranges? At least with your example here, using an AliasSeq is just complicating life. Dynamic arrays and ranges can be used at compile time via CTFE and are a lot more straightforward to use. - Jonathan M Davis
Re: Beta 2.074.0-b1
On 24/03/2017 6:35 PM, Martin Nowak wrote: First beta for the 2.074.0 release. This release comes with plenty of phobos additions and a new std.experimental module. http://dlang.org/download.html#dmd_beta http://dlang.org/changelog/2.074.0.html Please report any bugs at https://issues.dlang.org -Martin That "new" module isn't documented on the changelog.
Re: Comparing two AliasSeq
On Saturday, 25 March 2017 at 04:23:31 UTC, Jonathan M Davis wrote: On Saturday, March 25, 2017 03:25:27 Yuxuan Shui via Digitalmars-d-learn wrote: In this example: import std.range; template expandRange(alias R) if (isInputRange!(typeof(R))) { static if (R.empty) alias expandRange = AliasSeq!(); else alias expandRange = AliasSeq!(R.front(), expandRange!(R.drop(1))); } /// unittest { import std.range; static assert (is(expandRange!(iota(0,5)): AliasSeq!(0,1,2,3,4))); } The static assert fails, why? Well, is expressions normally compare types, not values, and AliasSeq!(0, 1, 2, 3, 4), isn't a type and doesn't contain types. static assert(is(AliasSeq!int == AliasSeq!int)); passes, whereas static assert(is(AliasSeq!0 == AliasSeq!0)); does not. So, I expect that the issue is that you're dealing with values rather than types. You're also using : instead of ==, and : _definitely_ is for types (since it checks for implicit conversion, not equality), so it wouldn't have entirely surprised me if == worked when : didn't, but == doesn't either. What you proobably should do is either convert the AliasSeq's to dynamic arrays or ranges - e.g. [AliasSeq!(0, 1, 2, 3, 4)] or only(AliasSeq!(0, 1, 2, 3, 4)) - though in both cases, that really only makes sense when you already have an AliasSeq, since [] and only will take the values directly. - Jonathan M Davis I see. I always thought tuple() is a type... So a tuple of types is a type, but a tuple of mixed types and values is not a type. Doesn't seem very consistent. Here is the solution I will go with: struct test(T...) { } import std.range; static assert (is(test!(expandRange!(iota(0,5))) == test!(0, 1, 2, 3, 4)));
Re: Comparing two AliasSeq
On Saturday, March 25, 2017 03:25:27 Yuxuan Shui via Digitalmars-d-learn wrote: > In this example: > > import std.range; > template expandRange(alias R) if (isInputRange!(typeof(R))) { > static if (R.empty) > alias expandRange = AliasSeq!(); > else > alias expandRange = AliasSeq!(R.front(), > expandRange!(R.drop(1))); > } > > /// > unittest { > import std.range; > static assert (is(expandRange!(iota(0,5)): > AliasSeq!(0,1,2,3,4))); > } > > The static assert fails, why? Well, is expressions normally compare types, not values, and AliasSeq!(0, 1, 2, 3, 4), isn't a type and doesn't contain types. static assert(is(AliasSeq!int == AliasSeq!int)); passes, whereas static assert(is(AliasSeq!0 == AliasSeq!0)); does not. So, I expect that the issue is that you're dealing with values rather than types. You're also using : instead of ==, and : _definitely_ is for types (since it checks for implicit conversion, not equality), so it wouldn't have entirely surprised me if == worked when : didn't, but == doesn't either. What you proobably should do is either convert the AliasSeq's to dynamic arrays or ranges - e.g. [AliasSeq!(0, 1, 2, 3, 4)] or only(AliasSeq!(0, 1, 2, 3, 4)) - though in both cases, that really only makes sense when you already have an AliasSeq, since [] and only will take the values directly. - Jonathan M Davis
Re: Comparing two AliasSeq
On Sat, Mar 25, 2017 at 03:25:27AM +, Yuxuan Shui via Digitalmars-d-learn wrote: > In this example: > > import std.range; > template expandRange(alias R) if (isInputRange!(typeof(R))) { > static if (R.empty) > alias expandRange = AliasSeq!(); > else > alias expandRange = AliasSeq!(R.front(), expandRange!(R.drop(1))); > } > > /// > unittest { > import std.range; > static assert (is(expandRange!(iota(0,5)): AliasSeq!(0,1,2,3,4))); > } > > The static assert fails, why? Firstly, is(T : U) expects T and U to be types, and expandRange!(...) is not a type (or a list of types), it is a list of values. Second, is(T : U) means "does the type T implicitly convert to the type U?". It checks for implicit convertibility between types, it does not compare values. T -- The right half of the brain controls the left half of the body. This means that only left-handed people are in their right mind. -- Manoj Srivastava
Re: RE: Are Gigantic Associative Arrays Now Possible?
On Friday, 24 March 2017 at 17:48:35 UTC, H. S. Teoh wrote: (In my case, though, B-trees may not represent much of an improvement, because I'm dealing with high-dimensional data that cannot be easily linearized to take maximum advantage of B-tree locality. So at some level I still need some kind of hash-like structure to work with my data. But it will probably have some tree-like structure to it, because of the (high-dimensional) locality it exhibits.) T Hi T, Your problem is intriguing and definitely stretching my mind! I'll be factoring your ideas into my app design as I go along. Some techniques that might be relevant to your app, if only for relative performance comparisons, might be: Using metadata in lieu of actual data to maximize the number of rows "represented" in the caches. Using one or more columnstores, both the intra- and extra-cache, to allow transformations of one or more fields of one or more rows with extremely small read, computation and write costs. Scaling the app horizontally, if possible. Using stored procedures on a a SQL NoSQL or NewSQL DBMS to harness the DBMS's bulk-processing and high-throughput capabilities. I'd love to hear whatever details you can share about your app. Alternatively I made a list of a dozen or so questions that would help me think about how to approach your problem. If you're interested in pursuing either avenue, let me know! Thanks again
Comparing two AliasSeq
In this example: import std.range; template expandRange(alias R) if (isInputRange!(typeof(R))) { static if (R.empty) alias expandRange = AliasSeq!(); else alias expandRange = AliasSeq!(R.front(), expandRange!(R.drop(1))); } /// unittest { import std.range; static assert (is(expandRange!(iota(0,5)): AliasSeq!(0,1,2,3,4))); } The static assert fails, why?
Re: More exception classes into Phobos?
On Friday, 24 March 2017 at 19:38:14 UTC, H. S. Teoh wrote: Catching an Exception by message? That sounds like horrible code smell to me. Yes, it is. That's why I think exception strings are an antipattern. You should be making new classes, not new strings. But, D lets us have both worlds. Consider the following: --- class MallocedException : Exception { @nogc this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null) { super(msg, file, line, next); } @nogc private void freeSelf() { import core.stdc.stdlib; import core.stdc.stdio; printf("freeing\n"); free(cast(void*) this); } ~this() { freeSelf(); } } class RaisedException(string msg) : MallocedException { @nogc this(string file = __FILE__, size_t line = __LINE__, Throwable next = null) { super(msg, file, line, next); } } class RaisedExceptionDetails(string message, T...) : RaisedException!message { T args; @nogc this(T args, string file = __FILE__, size_t line = __LINE__, Throwable next = null) { this.args = args; super(file, line, next); } override void toString(scope void delegate(in char[]) sink) const { import core.internal.traits : externDFunc; alias sizeToTempString = externDFunc!("core.internal.string.unsignedToTempString", char[] function(ulong, char[], uint) @safe pure nothrow @nogc); char[20] tmpBuff = void; sink("RaisedException"); sink("@"); sink(file); sink("("); sink(sizeToTempString(line, tmpBuff, 10)); sink(")"); if (message.length) { sink(": "); sink(message); } foreach(idx, arg; args) { sink("\n\t["); sink(sizeToTempString(idx, tmpBuff, 10)); sink("] = "); static if(is(typeof(arg) : const(char)[])) sink(arg); else static if(is(typeof(arg) : long)) sink(sizeToTempString(arg, tmpBuff, 10)); else {} // FIXME support more } if (info) { try { sink("\n"); foreach (t; info) { sink("\n"); sink(t); } } catch (Throwable) { // ignore more errors } } } } @trusted @nogc void raise(string msg, string file = __FILE__, size_t line = __LINE__, T...)(T args) { import core.stdc.stdlib, std.conv; enum size = __traits(classInstanceSize, RaisedExceptionDetails!(msg, T)); void* buffer = malloc(size); assert(buffer !is null); throw emplace!(RaisedExceptionDetails!(msg, T))(buffer[0 .. size], args, file, line); } void main() { raise!"my_exception"(12, "additional info", 32); } --- That raise line lets you define your string if you must, as well as *any* other data you want to pass along, with a usable, if a bit less than ideal, toString representation of it. BTW, I also went ahead and made this @nogc to show that's not really so hard to do. If you catch a MallocException, just .destroy(it). Easy (at least if you control both sides of the code). Notice that there are also no Phobos imports and no user allocations at the raise site. The only thing I'd add to it is some kind of raise!YourExceptionBase overload and I'd find this pretty useful. It probably makes sense for 3rd party libraries to have at least a subclass of Exception, so that you can catch errors originating from that library rather than everything in general. I tend to do very broad classifications. My script.d, for example, can throw three supertypes of exception: compile exception, runtime exception, and user-defined exceptions out of the script. Those are the things you'd likely catch, because each one has a different yet reasonable possible response. But, if additional info is easy to attach, I'd go ahead and do that too - there's just no reason not to when it is easy, and the catcher can then decide to get into more details if interested, or just catch one of the super classes if not. Actually, I see this as evidence *against* having RangeError in the first place. If we had stuck to throwing Exception or, in this case, Error, that would have prompted whoever wrote the bounds check code to actually write a useful error message Come on, be realistic.
Re: Exporting template function instances to C
On Friday, 24 March 2017 at 01:00:31 UTC, Nicholas Wilson wrote: On Thursday, 23 March 2017 at 19:46:43 UTC, data pulverizer wrote: On Thursday, 23 March 2017 at 17:58:21 UTC, H. S. Teoh wrote: On Thu, Mar 23, 2017 at 05:29:22PM +, data pulverizer via Thanks. Is there a less ham-handed way of exporting them other than wrapping them in functions as I have? Wrapping them in functions is probably the simplest way to call them from C. You *could*, I suppose, use their mangled names directly, then you wouldn't need a wrapper, but that would be rather difficult to use on the C end. On the D side, there's .mangleof that will tell you what mangled names to use, but if you're calling from C you don't have that luxury. T Thanks. Mangling sounds painful and scary, I think I'll stick to wrapping which sounds much less dangerous. There's nothing scary or dangerous about it. It happens automatically to allow overloads and templates so that you get a unique symbol foreach version (unless you use extern(C), extern(C++) or pragma mangle). C++,Java and any other compiled language that has overloads does mangling. Heck, you can even do it in C with __attribute__((overloadable)) (at least with clang), it just transparently mangles (just as in D)the name as whatever C++ would mangle it as. So instead of doing T mult(T)(T x, T y) { return x*y; } doing something like template mult(T) { extern(C++) T mult(T x, T y) { return x*y; } } in D, and then in C (noting that you have to declare the name and signature anyway) __attribute__((overloadable)) float mult(float,float); __attribute__((overloadable)) double mult(double, double); which I think is the least painful way of doing it. I seem to remember somewhere in phobos template Instantiate(alias a) { alias Instantiate = a; } to instantiate template, because you reference them from another symbol it somehow magically works. Used like Instantiate!(mult!float); // at module scope Thanks a lot ... I was half joking playing with the name "mangling" but I appreciate your explanations and suggestions.
Re: Parameterized template value parameter
On Friday, 24 March 2017 at 21:13:26 UTC, Yuxuan Shui wrote: On Friday, 24 March 2017 at 20:43:18 UTC, Dmitry Olshansky template A(alias str) if(is(typeof(str) : Char[], Char)){ alias Char = typeof(str[0]); // ... } One problem of this is that 'str' is not longer restricted to be a compile time value. Which is probably fine, but kind of makes me uncomfortable. To test wether str is a compile time value just check if you can use it to assign to an enum if(is(typeof(str) : Char[], Char) && is(typeof({enum foo = str;})))
Re: Yet another project with vibe.d
On Friday, March 24, 2017 12:23:23 Chris via Digitalmars-d wrote: > I just wanted to say thank you for vibe.d, Sönke and Kai (for the > book). I use vibe.d for all new web projects, and it's great. > Less and less JS, more and more D. It's also very fast. > > The way we use it is that we set up little vibe.d servers behind > the scenes and redirect to them. As in you use something like nginx on the outside and have it send requests on to vibe.d if they get past whatever blocking or whatever else you have set up with the external server? So, anyone talking the server sees nginx, but the actual website content or REST API or whatever is done by vibe.d? - Jonathan M Davis
Re: relax disabled Final!T unary operators
On Friday, March 24, 2017 11:00:20 H. S. Teoh via Digitalmars-d wrote: > All in all, it seems that Final, as currently implemented, really only > makes sense for class types. It seems to have glaring holes and > inconsistency problems with other types. (Just wait till I try it on a > union... that's gonna throw things off, I'm almost certain.) Well, final in Java (which is what I assume Final is trying to emulate) is basically head-const. So, if you have a pointer or reference, it would be const, and the rest would be mutable, whereas for types that are not essentially pointers end up being fully const. As such, I would have half-expected Final to just work with pointers and class references, but if it did work with other types, then either it would make anything directly in the type read-only, or it would make the whole type const. Even trying to emulate Java's semantics, it does get a bit funny, because all aggregate types in Java are reference types. So, something like a struct containing a pointer just isn't something that Java's final has to worry about, and if we're trying to emulate it, we're forced to come up with our own semantics. However, I think that what's most in the spirit of Java's final would be to make everything directly in the struct read-only - which in the case of dynamic arrays (which are essentially a struct) would mean that you could alter the elemens but not ptr or the length (regardless of whether altering the length would alter ptr). Now, how implementable that is, I don't know (certainly, it sounds like there are currently quite a few problems with what we currently thave), but if we can't do it right, we should probably just restrict Final to classes and pointers. I don't really have much of a horse in the race though, because I've always thought that Java's final was an utter waste of time. It's making exactly the wrong thing const. If we have it, I'd like to see it implemented in a manner which is not buggy and full of holes, because quality matters, but I don't really think that it was worth adding in the first place. - Jonathan M Davis
Re: Parameterized template value parameter
On Friday, 24 March 2017 at 20:43:18 UTC, Dmitry Olshansky wrote: On 3/24/17 12:24 AM, Yuxuan Shui wrote: So I was trying to make my template take a value parameter, whose type is also a parameter to the template. e.g.: template A(Char[] str, Char); But dmd complains about 'Char' being undefined. I have to write: template A(Char, Char[] str); Which is inconvenient, because now 'Char' can't be deduced by the compiler. Can we make the first case work? How about this? template A(alias str) if(is(typeof(str) : Char[], Char)){ alias Char = typeof(str[0]); // ... } Yes. This is what I ended up doing (https://github.com/yshui/sdpc/blob/master/sdpc/parsers.d#L45). One problem of this is that 'str' is not longer restricted to be a compile time value. Which is probably fine, but kind of makes me uncomfortable. In general it's sometimes possible to do the deduction w/o introducing more template arguments. --- Dmitry Olshansky
Re: Parameterized template value parameter
On 3/24/17 12:24 AM, Yuxuan Shui wrote: So I was trying to make my template take a value parameter, whose type is also a parameter to the template. e.g.: template A(Char[] str, Char); But dmd complains about 'Char' being undefined. I have to write: template A(Char, Char[] str); Which is inconvenient, because now 'Char' can't be deduced by the compiler. Can we make the first case work? How about this? template A(alias str) if(is(typeof(str) : Char[], Char)){ alias Char = typeof(str[0]); // ... } In general it's sometimes possible to do the deduction w/o introducing more template arguments. --- Dmitry Olshansky
[Issue 17274] New: No OS X .dmg file for DMD 2.074.0-b1
https://issues.dlang.org/show_bug.cgi?id=17274 Issue ID: 17274 Summary: No OS X .dmg file for DMD 2.074.0-b1 Product: D Version: D2 Hardware: x86 OS: Mac OS X Status: NEW Severity: enhancement Priority: P1 Component: dlang.org Assignee: nob...@puremagic.com Reporter: jrdemail2000-dl...@yahoo.com The DMD download page (http://dlang.org/download.html#dmd) has a link to the 2.074 beta-1 release (http://downloads.dlang.org/pre-releases/2.x/2.074.0/dmd.2.074.0-b1.dmg), but the file does not exist in the directory (http://downloads.dlang.org/pre-releases/2.x/2.074.0/). --
[Issue 17273] why is a const range not a range
https://issues.dlang.org/show_bug.cgi?id=17273 ag0ae...@gmail.com changed: What|Removed |Added Status|NEW |RESOLVED CC||ag0ae...@gmail.com Resolution|--- |INVALID --- Comment #1 from ag0ae...@gmail.com --- Because you can't call popFront on it. Closing as invalid. Please make a thread in the learn forum if this doesn't make sense to you. https://forum.dlang.org/group/learn --
Re: More exception classes into Phobos?
On Fri, Mar 24, 2017 at 01:44:02AM +, Adam D. Ruppe via Digitalmars-d wrote: > On Friday, 24 March 2017 at 00:28:16 UTC, Walter Bright wrote: > > The string is what gets printed to the user like: > > > >"your password has to have at least one upper case character in > >it" > > > > In general, such is not deducible from the type/arguments. > > Yes, of course they are. In the simplest case in D, we could do throw > new ExceptionImpl!string instead of throw new Exception(string), then > it is absolutely deducible from the type, since it is a part of the > type by definition. > > That also becomes catchable independently of other exceptions (have > you ever done something like `catch(Exception e) if(e.msg != "foo") > throw e;`? I actually have literally done that with a crappy D library > that threw an exception that I could recover from with a retry...), > avoids any runtime allocation of the string, and is potentially easier > to internationalize if you want to present it to the end user. Catching an Exception by message? That sounds like horrible code smell to me. Upgrade the 3rd party library (which may change the message) and suddenly your program breaks. Bad idea. It probably makes sense for 3rd party libraries to have at least a subclass of Exception, so that you can catch errors originating from that library rather than everything in general. Beyond that, though, you're treading into implementation details territory, which is IMO a bad idea in terms of breaking encapsulation, overly tight coupling between thrower/catcher, etc.. A better way, though, is for the library to provide a retry mechanism in the first place, as part of the official API, than to rely on the caller catching an exception and identifying it. > That's not how I'd literally do it, but it is something we CAN do in D > (and would be an improvement from the status quo, without being a > hassle of hierarchies). Generally, I find that I do subclass Exception in my own code, for obvious reasons, including that since it's my own code, the rest of the code knows what to catch and what to do about it. It basically becomes an API common to code in that particular project that defines certain exception subclasses with known semantics. In 3rd party libraries, I can see a handful of exception subclasses publicly documented for that library as part of its API as stuff specific to that library that may get thrown. But I don't see how to generalize that across libraries... by that point, it will have to become so generic that it's no better than just throwing Exception with a string message. > > Exceptions are not for debugging the code (that's what Errors are > > for), Exceptions are for informing the user that he did it wrong. > > All the more reason to actually make them as informative as possible (...and > likely to cut out most the irrelevant stack trace). If the user is another > programmer calling your function, they ought to be able to catch and inspect > the exception in order to retry. > > Moreover, informing the user wants to have as much info as possible. We've > probably all been frustrated by in D by "Range violation" but it doesn't > tell us what the value actually was. Attaching an int and sinking it into > the error message ought to be trivial... and it IS, yet druntime doesn't do > it. (and yes, I know that's an Error, not an Exception, but same reasoning > applies) Actually, I see this as evidence *against* having RangeError in the first place. If we had stuck to throwing Exception or, in this case, Error, that would have prompted whoever wrote the bounds check code to actually write a useful error message instead of just throwing RangeError with zero additional details. (Since, after all, the exception type ought to be enough to tell the user what needs to be known.) > I only care about the hierarchy insomuch as I intend to catch it > without catching something else from the same block of code. > > > try { > throw new RangeErrorImpl!(size_t, size_t, size_t)(x, 0, array.length); > } catch(RangeError e) { > // this suddenly became a billion times more useful > e.toString(sink); // RangeError, 10, 0, 8 > } Except that it's not really *that* useful if you don't know what those numbers mean. They could be values taken from CPU registers in a stacktrace for all I know, which tells me nothing. Meaning that you might as well have formatted those numbers into part of the string message in the first place. A similar discussion came up some years ago, where Andrei proposed adding a Variant[string] field to Exception where the thrower can stick whatever details he likes into it. Again, though, the problem is, how would the catcher know what string keys to use to get useful info out of that field, and what the values might mean. Unless there is some documented standard, it's really not of much use. It's like receiving an XML file with no DTD. Yeah I'm sure the meaning is all there
Re: Learning programming with D - optimizing the entry point / the environment?
On Thu, Mar 23, 2017 at 06:48:32PM +, Adam D. Ruppe via Digitalmars-d wrote: > On Thursday, 23 March 2017 at 18:25:55 UTC, H. S. Teoh wrote: > > And BTW, that was written for a text console, so the only library > > needed was a terminal control library (which in theory could be > > dispensed with, as you could just output the escape sequences > > yourself / call the OS console functions yourself). > > Oh, my terminal.d makes that simple anyway! Oh yeah, I've found terminal.d to be extremely useful in the little console apps I've been writing. Thanks for that! Before I came across terminal.d, I had to resort to binding with lib[n]curses, whose API is a sorry mess, esp. when Unicode is involved. (Plus, many API functions are implemented as C macros, which makes it a royal pain to interface with D code -- I basically had to wrap them in an additional C wrapper library on top of linking in libncurses in the first place.) > I want to close some of the gap between terminal and simpledisplay > though. I wrote a little file text viewer for someone on irc today > with simpledisplay and it was a bit of a hassle. On the other hand, a > high-level widget is outside sdpy's charter, but being able to write > text is really useful... and surprisingly complicated with low-level > apis, so I think I'll do something. > > But regardless, for a 2d game, sdpy and terminal both give what you > need to make it pretty simple. Technically, it would work for a "3D" game too, if you're willing to sacrifice the realism of 3D perspective projection and settle with 2D slices of 3D. :-P (Hey, if that works for 4D, why not for 3D?) T -- It said to install Windows 2000 or better, so I installed Linux instead.
Re: Of the use of unpredictableSeed
On Tue, Mar 21, 2017 at 10:11:44PM +, sarn via Digitalmars-d wrote: > On Tuesday, 21 March 2017 at 10:27:27 UTC, Andrei Alexandrescu wrote: > > Thanks Yuxuan, sorry for missing this. Can we have this peer > > reviewed by 1-2 crypto experts? Thanks! -- Andrei > > By API, unpredictableSeed() only returns a 32b uint and will never > meet crypto standards. Beware of anyone who offers to review it based > on their "crypto expertise". > > unpredictableSeed() is just for things like making single-player games > more interesting. It simply isn't for security, and that's pretty > much what cym13's post was about. Yeah, why is it that people still keep thinking unpredictableSeed(), or indeed, the whole of the current std.random, is useful for *anything* related to crypto?? If you want to do crypto, you should be using a crypto library that is *designed* to be cryptographically secure and *verified* by cryptoanalysts to be secure. std.random is a far cry from that, and crypto isn't even its charter anyway. What std.random is useful for is to make games more interesting, or for certain kinds of Monte Carlo simulations. (Note that some Monte Carlo simulations may be sensitive to hidden patterns in std.random PRNGs, so you should choose your PRNG carefully, and/or take the simulation results with a grain of salt.) Or for things like probabilistic algorithms (e.g., probabilistic approximate solution finders for NP-complete problems and the like). Using it for anything crypto- or security-related is just begging to be hacked, esp. in this day and age. T -- Why waste time learning, when ignorance is instantaneous? -- Hobbes, from Calvin & Hobbes
Re: bug in foreach continue
On Thu, Mar 23, 2017 at 05:11:49PM +, Adam D. Ruppe via Digitalmars-d-learn wrote: > On Thursday, 23 March 2017 at 00:39:56 UTC, H. S. Teoh wrote: > > I'm still working on that. :-) > > Hey, can you at least put scare quotes around "static foreach" each > time it is used? There's no such thing as static foreach and while we > might call foreach over a typetuple "static", it isn't a precise term > and invites additional confusion. Done. I've gotten the draft into a semi-acceptable state, though I'm still not fully satisfied with it just yet. But perhaps now is a good time to solicit input from forum members, so here's the link to the draft: https://wiki.dlang.org/User:Quickfur/Compile-time_vs._compile-time T -- It always amuses me that Windows has a Safe Mode during bootup. Does that mean that Windows is normally unsafe?
Dlang Boston Meetup - Hack-a-thon
For those D enthusiasts living in or around Boston, I've scheduled a mini hack-a-thon for next Friday 3/31 in the Back Bay. Would be great to see you all there! Details here: https://www.eventbrite.com/e/dlang-boston-hack-a-thon-tickets-33151627410 I will cross post to meetup.com in a bit. -Steve
COM2D Wrapper
I'd like to present the following D library I am working on: https://github.com/IllusionSoftware/COM2D It attempts to automate COM in D. It has some problems but does partially work. Those with a recent version of Adobe Photoshop and an interest in COM can try it out and make contributions if they would like to see it progress. The goal is to completely remove the necessity to use COM api in D and simply use D directly. When executing the application, photoshop should start up. One must use a debugger or modify the main.d app to see what is happening. So far, only the top most interface is working as aggregates have not been handled. If anyone is interested in seeing this through, maybe we can collaborate to get a fully functional implementation.
[Issue 17273] why is a const range not a range
https://issues.dlang.org/show_bug.cgi?id=17273 Sahmi Soulaïman (سليمان السهمي)changed: What|Removed |Added Keywords||rejects-valid --
[Issue 17273] New: why is a const range not a range
https://issues.dlang.org/show_bug.cgi?id=17273 Issue ID: 17273 Summary: why is a const range not a range Product: D Version: D2 Hardware: x86 OS: Linux Status: NEW Severity: critical Priority: P1 Component: phobos Assignee: nob...@puremagic.com Reporter: sahmi.soulaim...@gmail.com the following code works for me. the second assert should fail: import std.range; unittest { static assert(isInputRange!(InputRange!int)); static assert(!isInputRange!(const(InputRange!int))); } $ dmd --version DMD32 D Compiler v2.073.0 Copyright (c) 1999-2016 by Digital Mars written by Walter Bright --
Re: relax disabled Final!T unary operators
Another grey area (or more precisely, problematic area) with Final is dynamic arrays. To wit: Final!(int[]) arr; arr.length += 1;// correctly rejected arr.length = 10;// accepted - WAT? arr.ptr++; // correctly rejected arr.ptr = null; // correctly rejected Bugzilla: https://issues.dlang.org/show_bug.cgi?id=17272 Why is it that .length can be assigned, but arr.ptr cannot? (Note that altering .length may alter .ptr as well, even though direct assignment to .ptr is rejected.) It's probably an implementation detail of how Final is implemented... but still, this does raise the question: should Final allow changing aggregate members? Dynamic arrays being a special kind of aggregate in that we normally think of their members as the array elements themselves, but in implementation dynamic arrays are slices, which are structs consisting of a pointer and a length. If Final is meant to be head-const, wouldn't the "head" portion be .length and .ptr? So we ought to reject any attempt to modify them. But on the other hand, if we allow modifying Final struct members, then this is again inconsistent. All in all, it seems that Final, as currently implemented, really only makes sense for class types. It seems to have glaring holes and inconsistency problems with other types. (Just wait till I try it on a union... that's gonna throw things off, I'm almost certain.) T -- Those who've learned LaTeX swear by it. Those who are learning LaTeX swear at it. -- Pete Bleackley
Re: sdpc - Simple/Stupid D parser combinator
On Friday, 24 March 2017 at 17:53:14 UTC, Basile B. wrote: On Thursday, 23 March 2017 at 22:55:10 UTC, Yuxuan Shui wrote: [...] Thanks for sharing this but your project is not visible! Gitlab is a bit confusing because by default repositories are private. Go to your project setting(should be https://gitlab.com/yshui/sdpc/edit): - set "Project Visibility" to "public". - set "Repository" to "everyone with access". Thanks for pointing this out! Obviously I only set "Visibility" to "public" and forgot the other settings...
Re: RE: Are Gigantic Associative Arrays Now Possible?
On Fri, Mar 24, 2017 at 04:59:00PM +, dlangPupil via Digitalmars-d wrote: [...] > In addition to prevalence of random lookups, certain additional app > conditions and designs might make "gigantic AAs" more useful or > competitive with alternatives: > > 1. Use by programmers who need a data structure that's easier to > reason about or faster and safer to implement or prototype, and easier > for future users to read and maintain. This point is arguable, since a B tree is pretty well-known and thus not difficult to reason about. Generally, whether you use a hashtable of a B tree or something else, the high-level view is that it's some opaque data structure that, given some key K, returns some value V. Which underlying algorithm is used is an implementation detail. And generally as far as application programmers are concerned, you wouldn't want to implement an advanced data structure from scratch; you'd use an off-the-shelf library that has already implemented it. > 2. Apps with large tables that use (or could use) non-natural keys, > e.g., crypto-quality GUIDs, which can't benefit from (or impose the > extra computational cost of) the sorting that must be performed and > maintained on natural key values (e.g., LastName="Smith") in order to > use a B-Tree search. Encrypted GUIDs is a very good point. You probably can't expect much locality from that. But this point, and the following, presume a rather specific use case, i.e., document retrieval, presumably over the network. The application of hashtables and B-trees, however, is far wider in scope. In particular, what I had in mind when I asked about cache speeds is compute-intensive (as opposed to I/O intensive) processes. These two domains of application are quite different in some ways. In document retrieval, for example, if you view it as a server serving documents over the network to a set of clients, having 1 I/O roundtrip per lookup is probably acceptable, because the time it takes to send the document over the network to the client is large enough that making lookups any faster probably won't make too much of a difference. Besides, if client requests are essentially unpredictable, then 1 I/O roundtrip is about the best you could do. In CPU-intensive computations, however, the cache hierarchy becomes very prominent, because you're talking about CPU speeds vs. RAM speeds, which is currently a rather large gap. Being cache-friendly could mean a difference on the scale of orders of magnitude in terms of overall performance. If you're talking about data lookups inside a compute-intensive inner loop, having 1 I/O roundtrip per iteration is unacceptable. Even 1 L1 cache miss per iteration may be unacceptable, depending on the application. Ideally, you want to maximize the number of iterations per L1 cache miss, and then on the next level, squeeze as many L1 misses onto L2 as possible before you have to go to L3 or revert to RAM, because RAM is slow, relatively speaking, even if it's still very fast compared to an I/O roundtrip to the hard disk. In other words, you want as much locality as you can possibly get in your memory accesses -- the entire cache hierarchy, after all, is built on the premise of memory accesses exhibiting locality. Furthermore, when it comes to CPU-intensive applications, quite often you already know the pattern of lookups beforehand, since it's usually coming from within the application itself, not from external clients that may be completely unpredictable. So you can usually predict the next n memory accesses much more easily, and take advantage of it by organizing your data structure around that. [...] > Finally, re: caches: I haven't found whether it is or isn't possible > to combine a server's DRAM and its Optane SSD RAM or DIMMs to form a > single pool of RAM. Mixing DIMMS of different speeds is a no-no; but > if this could be done, then the hottest data could be "cached" in DRAM > and thus spared the 10x latency penalty of the SSD device. If the SSD device incurs a 10x latency penalty, that's still a far cry from L1/L2 cache latencies! True, it will help in the worst case when you have no choice but to take an I/O roundtrip (a hard drive would be far slower)... but this would hardly be anything revolutionary if DRAM is still faster. At the end of the day, you're still talking about a memory hierarchy with L1/L2 at the top, L3 and RAM in between, and hard drive / SSD at the bottom. If so, then the cache-unfriendliness of hashtables still applies, and we still have to work with finding ways of improving hashtable locality, e.g., with locality-sensitive hashing, cache-oblivious hashtables, etc., or use a more cache-friendly data structure like B-trees or one of the newer cache-oblivious trees. (In my case, though, B-trees may not represent much of an improvement, because I'm dealing with high-dimensional data that cannot be easily linearized to take maximum advantage of B-tree locality. So at some
Re: sdpc - Simple/Stupid D parser combinator
On Thursday, 23 March 2017 at 22:55:10 UTC, Yuxuan Shui wrote: GitLab: https://gitlab.com/yshui/sdpc Documents: https://yshui.gitlab.io/sdpc Dub: http://code.dlang.org/packages/sdpc I started this project ~1.8 years ago. It only took me a couple of weeks to write, and I learned a lot about D's template system (and its limitations) by writing it. But back then I wasn't confident with the code quality and documentation enough to make it public. Then life caught up with me and I can't spend time on it. Recently I finally got some time and decided to cleanup the code and make it available to more people. Now I'm comfortable with it enough to have more eyes on it. sdpc is a very simple parser combinator library. So it lacks some bells and whistles like left recursion or memoization. But it should be able to handle a lot of the simpler use cases. (I know we have pry now. A bit of competition won't hurt =] ). Thanks for sharing this but your project is not visible! Gitlab is a bit confusing because by default repositories are private. Go to your project setting(should be https://gitlab.com/yshui/sdpc/edit): - set "Project Visibility" to "public". - set "Repository" to "everyone with access".
Re: Beta 2.074.0-b1
On 03/24/2017 06:35 PM, Martin Nowak wrote: > First beta for the 2.074.0 release. > > This release comes with plenty of phobos additions and a new > std.experimental module. > > http://dlang.org/download.html#dmd_beta > http://dlang.org/changelog/2.074.0.html Forgot to mention, the packages don't contain documentation, we have to fix a couple of integration issues with the build scripts and dlang.org's makefile. -Martin
Beta 2.074.0-b1
First beta for the 2.074.0 release. This release comes with plenty of phobos additions and a new std.experimental module. http://dlang.org/download.html#dmd_beta http://dlang.org/changelog/2.074.0.html Please report any bugs at https://issues.dlang.org -Martin
Re: How to use C code in D
On Thursday, 23 March 2017 at 18:10:20 UTC, Dillen Meijboom wrote: Hi there, I'm learning D for a while because it's really easy to use C-code in D. The problem is that I don't really get how to deal with the data structures defined in C in D. Perhaps, it will be interesting to you. I advise to look at https://www.youtube.com/watch?v=HTgJaRRfLPk
Re: RE: Are Gigantic Associative Arrays Now Possible?
On Friday, 24 March 2017 at 06:30:25 UTC, H. S. Teoh wrote: You have to keep in mind that one downside of hashtables is that they tend to be unfriendly towards caching hierarchies ... For certain applications, where key lookups are more-or-less random, this is the best you could do, but for a good number of applications, there tends to be some correlation between lookups, and even things like B-trees could potentially do better because of their cache-friendliness (and locality), even if you assume I/O is much faster than your traditional spindle-based hard drive. The O(log n) could have a much smaller constant than the hashtable O(1) if lookups tend to be correlated (i.e., exhibit locality), and lots more cache misses are incurred in the latter. Having said that, though, large-capacity low-latency SSDs are very interesting to me because I'm interested in certain applications that involve very large lookup tables. Currently I'm just using traditional hashtables, but once you get to a certain size, I/O overhead dominates and progress grinds to a halt. I've been researching ways of taking advantage of locality to ease this, but so far haven't gotten it to actually work yet. T Thanks T for the great insight. Very helpful! Nice to see that you, Laeeth, the ACM, Intel and Micron all agree: this new technology could be very disruptive. In addition to prevalence of random lookups, certain additional app conditions and designs might make "gigantic AAs" more useful or competitive with alternatives: 1. Use by programmers who need a data structure that's easier to reason about or faster and safer to implement or prototype, and easier for future users to read and maintain. 2. Apps with large tables that use (or could use) non-natural keys, e.g., crypto-quality GUIDs, which can't benefit from (or impose the extra computational cost of) the sorting that must be performed and maintained on natural key values (e.g., LastName="Smith") in order to use a B-Tree search. 3. Tables (and related tables) whose row data (and even aggregate data) could be "clumped" (think "documentized") to achieve a singularity (and not merely some degree of locality), thus consolidating multiple lookups into a single lookup. -In other words, a key's value is itself an array of data that can be fetched in a single lookup. -The key id for each "next" (updated) version of a document could also be stored with the current version. -The next key-value entry to hold the update could be created immediately but not have its values written unless and until the prior version of the document has changed. -Better yet in an append-only design, creation of the next key-value entry could be deferred until a revision actually occurs. -Such "chained documentization" would automate histories, and could be further abstracted and adapted (e.g., with columnstore concepts) to accommodate apps in which lookups aren't mostly random. Finally, re: caches: I haven't found whether it is or isn't possible to combine a server's DRAM and its Optane SSD RAM or DIMMs to form a single pool of RAM. Mixing DIMMS of different speeds is a no-no; but if this could be done, then the hottest data could be "cached" in DRAM and thus spared the 10x latency penalty of the SSD device.
Re: The delang is using merge instead of rebase/squash
On Tuesday, 21 March 2017 at 20:16:00 UTC, Atila Neves wrote: git rebase master my_branch git checkout master git merge --no-ff my_branch Yes, that's about what we aim for, rebase w/ --autosquash though, so that people can `git commit --fixup` new fixup commits to open PRs w/o leaving noise behind. https://github.com/dlang-bots/dlang-bot/issues/64 Requires a local checkout of the repo which the bot doesn't have atm.
Re: Multi-commit PRs vs. multiple single-commit PRs
On Tuesday, 21 March 2017 at 12:49:22 UTC, Vladimir Panteleev wrote: On Tuesday, 21 March 2017 at 11:59:42 UTC, deadalnix wrote: Then it should have been 2 PR or more to begin with. Splitting PR in smaller ones is a good practice in general, This is probably true for many cases, but I don't think it's a general truth. Let's please not conflate a small technical discussion about how to preserve information in git (e.g. squash vs. merge vs. rebase) with a workflow debate about proper PR size.
[Issue 15726] [REG2.068.0] forward reference error for circular classes, RefCounted
https://issues.dlang.org/show_bug.cgi?id=15726 --- Comment #5 from github-bugzi...@puremagic.com --- Commit pushed to stable at https://github.com/dlang/dmd https://github.com/dlang/dmd/commit/f429983efbeb78aa727827ae7d76a728996b4d4d Fix wrong fields.dim value from test13613. This is a regression from fixing issue 15726, which caused gdc to ICE because it actually verifies the contents of the frontend AST are correct. --
Re: Amper audio player for GNU/Linux and X11
some updates: * region.txt support for skins; * reworked equalizer (smaller, faster); * background scanner for playlist items (Amper won't hang when adding alot of files to playlist anymore); * ID3v2 parser, so mp3s will have (some) metainfo too; * fully configurable global hotkeys (including hotkeys for playback control); * better on-the-fly skin reloading; * pure X11 renderer, so Amper is using much less memory now.
Re: How to use C code in D
On Thursday, 23 March 2017 at 18:10:20 UTC, Dillen Meijboom wrote: Hi there, I'm learning D for a while because it's really easy to use C-code in D. The problem is that I don't really get how to deal with the data structures defined in C in D. D makes it easy to utilize C code, but there is no magic C to D wrapper. There are some functions in Phobos which help (e.g. toStringz). You can slice a C string to utilize it as a slice, but usually there are ownership issue with this approach. In my experience, you'll be writing some C style code to provide a D interface.
DMD Git master regression: disabled postblits during CTFE
The file https://github.com/nordlow/gmp-d/blob/master/src/gmp/z.d in my https://github.com/nordlow/gmp-d package errors during compilation with DMD Git master as z.d(2350,16): Error: struct gmp.z.MpZ is not copyable because it is annotated with @disable Specifically, this happens in the return statement in the compile-time call of eval() during in the `static assert` here: /// `MpZ`-`MpZ` adding expression. struct MpzAddExpr(T1, T2) if (isMpZExpr!T1 && isMpZExpr!T2) { T1 e1; // first term T2 e2; // second term pragma(inline, true) MpZ eval() const @trusted { typeof(return) y = null; __gmpz_add(y._ptr, e1.eval()._ptr, e2.eval()._ptr); version(ccc) ++y._ccc; return y; } } version(unittest) static assert(isMpZExpr!(MpzAddExpr!(MpZ, MpZ))); It seems like CTFE no longer allows the `Mpz`-instance to be moved in the `return` statement of `eval()`. This doesn't happen with 2.073.1.
Yet another project with vibe.d
I just wanted to say thank you for vibe.d, Sönke and Kai (for the book). I use vibe.d for all new web projects, and it's great. Less and less JS, more and more D. It's also very fast. The way we use it is that we set up little vibe.d servers behind the scenes and redirect to them.
Re: Multi-commit PRs vs. multiple single-commit PRs
On Friday, 24 March 2017 at 09:27:54 UTC, Vladimir Panteleev wrote: Yep, because of the misuse-worst-case arguments. Simple solutions that guard against such mistakes are welcome. E.g. we could allow squashing if all commits' commit messages except the first one's start with "[SQUASH] " or "fixup! ". Because it is meant to be the default, doing only when some specific message exist is not going to fly. Using !donotsquash or alike in the commit message is, however, a good way to proceed.
Virtual nested classes and "this"
Hi, I have been poking around with overriding internal classes, and after reading [1] it was actually not clear to me whether it could be done or not, so I started trying. The good news (for me, at least) is that it can mostly be done [2], whoever I have found a bit intriguing that I need to explicitly use "this.i" instead of just "i" in B.fb() [3]. Just in case, the code I got to work is this: ``` class A { public static class I { public string fai() { return "A.I.fai"; } } public string fa() { return i.fai(); } public this(this C)() { i_ = new C.I(); } protected I i_; public @property T.I i(this T)() { return cast(T.I) this.i_; } } class B : A { override public static class I : A.I { override public string fai() { return "B.I.fai"; } public string fbi() { return "B.I.fbi"; } } public this(this C)() { super(); } public string fb() { return this.i.fbi(); // Why is "this" needed here? } } void main() { A a = new A(); A ab = new B(); B b = new B(); assert (a.fa() == "A.I.fai"); assert (ab.fa() == "B.I.fai"); assert (b.fa() == "B.I.fai"); assert (b.fb() == "B.I.fbi"); } ``` Is there a reason for that? Why cannot it be inferred as in the regular case? Also, if there's a way to do it without using the property wrapper, I'd be glad to know it :) I tried something like: ``` template i(this T) { T.I i; } ``` but it didn't like it... I guess members have to be better defined... Best, A [1]: https://forum.dlang.org/thread/siwjqxiuocqtrldcz...@forum.dlang.org [2]: https://dpaste.dzfl.pl/8f4e0df438e5 [3]: https://dpaste.dzfl.pl/8f4e0df438e5#line-34
Re: Multi-commit PRs vs. multiple single-commit PRs
On Friday, 24 March 2017 at 05:56:57 UTC, Seb wrote: On Friday, 24 March 2017 at 05:10:54 UTC, Vladimir Panteleev wrote: I think that if you do not think that discussing this subject any further is worth your time, then you shouldn't allocate any of your time time towards it. As previously mentioned, I don't think the arguments presented here warrant changing the status quo, so it is all theorizing. FWIW (as mentioned before) the status quo is different to what's intended as auto-merge-squash has been disabled by Martin: https://github.com/dlang-bots/dlang-bot/issues/64 Yep, because of the misuse-worst-case arguments. Simple solutions that guard against such mistakes are welcome. E.g. we could allow squashing if all commits' commit messages except the first one's start with "[SQUASH] " or "fixup! ".
Re: RE: Are Gigantic Associative Arrays Now Possible?
On Fri, Mar 24, 2017 at 12:27:00AM +, dlangPupil via Digitalmars-d wrote: > On Thursday, 23 March 2017 at 10:27:36 UTC, Ola Fosheim Grøstad wrote: > > > > Increasing the size of a hash table would be prohibitively > > expensive. You need a data-structure that can grow gracefully. > > Hi Ola, > > Are the hash tables you refer to the ones that D uses in the > background to implement associative arrays, or the ones that a > programmer might create using AAs? > > --If the former, then perhaps the AA's hash function could be tweaked > for terabyte-range SSD "RAM". But even if the typical 2:1 bucket/data > storage ratio couldn't be improved, then creating 32 TB of buckets > would still allow 16 TB of nearly-instantly-addressable data (on a > 4-core Xeon w/ 48 TB Optane SSD). > > --If the latter, then my goal is design something that makes specific > items randomly and instantly accessible, like a hash table, but with > zero potential collisions. Thanks! How do SSD access speeds compare with L1 and L2 cache speeds? You have to keep in mind that one downside of hashtables is that they tend to be unfriendly towards caching hierarchies, because generally the hash function is designed to scatter hash keys as widely and as randomly as possible (to minimize collisions), meaning that potentially *every* hash lookup will be a cache miss, perhaps more, depending on how collision resolution is handled, which can be a big performance killer. For certain applications, where key lookups are more-or-less random, this is the best you could do, but for a good number of applications, there tends to be some correlation between lookups, and even things like B-trees could potentially do better because of their cache-friendliness (and locality), even if you assume I/O is much faster than your traditional spindle-based hard drive. The O(log n) could have a much smaller constant than the hashtable O(1) if lookups tend to be correlated (i.e., exhibit locality), and lots more cache misses are incurred in the latter. Having said that, though, large-capacity low-latency SSDs are very interesting to me because I'm interested in certain applications that involve very large lookup tables. Currently I'm just using traditional hashtables, but once you get to a certain size, I/O overhead dominates and progress grinds to a halt. I've been researching ways of taking advantage of locality to ease this, but so far haven't gotten it to actually work yet. T -- People say I'm indecisive, but I'm not sure about that. -- YHL, CONLANG
Re: Multi-commit PRs vs. multiple single-commit PRs
On Friday, 24 March 2017 at 05:10:54 UTC, Vladimir Panteleev wrote: I think that if you do not think that discussing this subject any further is worth your time, then you shouldn't allocate any of your time time towards it. As previously mentioned, I don't think the arguments presented here warrant changing the status quo, so it is all theorizing. FWIW (as mentioned before) the status quo is different to what's intended as auto-merge-squash has been disabled by Martin: https://github.com/dlang-bots/dlang-bot/issues/64