Re: DMD won't compile re-init of variable
On Thursday, 30 January 2020 at 21:36:53 UTC, Adam D. Ruppe wrote: On Thursday, 30 January 2020 at 21:09:41 UTC, Simon wrote: How do I revert my variable to the init state? null is the initial state for those. More generally, .init can be used as to get the initial state for any type. ie. m_string2edge = typeof(m_string2edge).init;
Re: CTFE Status 2
On Wednesday, 3 May 2017 at 07:35:56 UTC, Stefan Koch wrote: On Wednesday, 3 May 2017 at 06:10:22 UTC, Adrian Matoga wrote: So you're going to reinvent TCP in your debugging protocol? No. there is no need for a full blown recovery mechanism. For the typical usecase a lossless orderd connection can be assumed. And most things are not order dependent The debugger isn't a massive, real-time system that needs to service thousands of clients and squeeze as much performance out of the network as possible. The overhead incurred by TCP is essentially not worth considering for something that's going to be run over localhost 90%, and service just the one client. Reinventing the wheel adds a far bigger overhead: Maintaining your new protocol. TCP implementations are readily available. They're well maintained, well documented, and are essentially guaranteed to work across platforms. Implementing a new protocol just adds an extra point of breakage for little to no gain. It also incurs the cost of the associated development time, and - down the line - any time spent fixing or iterating. Not to mention that tests need to be written, documentation needs to be put in place. A classic case of premature optimization.
Re: RFC: patch statement
On Monday, 3 April 2017 at 11:16:57 UTC, Dejan Lekic wrote: I know people her do not like to see proposals that change (add stuff to) the language. However, I strongly feel that for the testing purposes D should provide means to patch any object (no matter whether it is final or not!). Therefore I wonder what people think of adding a `patch(obj) {}` or perhaps change the semantics of the `with(obj) {}` so unittest writers can modify the object and set values. The patch keyword would work ONLY inside unittest {} blocks AND inside functions annotated with @test annotation. Imagine we have: int myFun(Person person) { /* some logic here */ } unittest { auto p = new Person() /* does not really matter which constructor we use */ patch(p) { // here we can modify ANY attribute, no matter whether it is private or public p.fname = "Nikola" p.sname = "Tesla" } auto res = myFun(p) // do some assertions here } Similarly: @test void test_myFun() { // same code as in the unittest above. } I do not even know if patch() {} statement is even possible, that is the whole point of writing this, so people can enlighten me... :) As I said in the introduction paragraph, for this purpose the semantics of the with statement could be changed, but I prefer a different keyword (patch) to be honest. It looks like what you're trying to do is set up object mocks for unit testing. In general, I find that well designed libraries provide such tools for testing, either in the form of factory functions or some other means of constructing mocks for test builds. I try to follow such patterns myself. Getting back to the immediate subject: You can already grant write access to whatever attributes with a bit of conditional compilation. Notably, defining accessors that exist only for unittest builds. You could even go so far as to define a generalized one, ie. version(unittest) { void patch(string attr, T)(Person p, T value) { __traits(getMember, p, attr) = value; } } And then, elsewhere: // Given p is some Person. p.patch!"fname" = "Nikola"; p.patch!"sname" = "Tesla"; So long as this is defined in the same module as the type, it'll be able to access protected and private fields.
Re: If you needed any more evidence that memory safety is the future...
On Sunday, 5 March 2017 at 11:48:23 UTC, Jacob Carlborg wrote: On 2017-03-03 16:23, Moritz Maxeiner wrote: That would be a good next step from an engineering standpoint, I agree, to proceed to minimize the amount of trust in people you need to have vs verifiable safety. I have considered porting something like seL4[1] to Rust, but ultimately this would take a significant amount of time and even if done you'd then have the biggest problem any new kernel faces: Hardware support. Driver development is AFAIK mostly done by people working for the hardware manufacturer and you're going to have a hard (probably closer to impossible) time convincing them to spend money on driver development for you. And if they don't you'll have close to 30 years of hardware support to catch up on by yourself. But suppose you limit yourself to a single (or at most a handful of homogeneous) platform(s) like [2], e.g. a new AArch64 board. Suppose you even take one where the hardware is open so you can audit its schematics, then you'll *still* either have to use proprietary firmware for the (partially onboard) periphery (and have unsafe interfaces to them), or - once again - write all the device firmware yourself. And once you've done all of that you're still missing userspace, i.e. you have a nice new OS without any actual use for it (yet). So you either start writing your own incompatible, safe userspace, or you're going to decide to integrate the userspace of existing OSs (probably POSIX?) to your new OS, so you're going to be writing your own (safe) libc, (safe) pthread, etc, exposing (once again) unsafe APIs to the top. It will be safer than what we currently have on e.g Linux since you can probably make sure that unsafe use of them won't result in kernel exploits, though; this will, of course, take even more time. Finally, at the arduous end of your journey you're likely going to notice what - in my experience - most new OSs I've observed of the years experience: Essentially nobody is interested in actually switching to a volunteer-based OS. Honestly, I think you need serious corporate backing, a dedicated team, and like 5-10 years (low estimate) of guaranteed development time to have a snowballs chance in hell to pull this off and the only possible sponsors for this I'm both aware of and would currently trust not to cut you off in the middle are either already working on their own OS[3], or have dedicated their R to other things[4]. I agree. The only potential hope I see would be to port Linux to a memory safe language. By Linux, I hope you don't mean the kernel itself. Because outside of being an entirely fruitless venture, it shows a lack of understanding of what's involved in kernel programming. Most memory safe languages I know don't take well to using bit arithmetic with pointers, deliberately smashing the stack, self modifying code, and a whole plethora of things required to work with the CPU in a freestanding environment. Within the span of a single function call, an address in memory is easily able to refer to a different address on physical memory. Forgive me if I'm wrong, but I don't think you can get that much benefit out of memory safety when you change the address of the stack pointer manually and start to manually prefill it with new values for general registers.
Re: foreach for string[string]AA
On Tuesday, 28 February 2017 at 18:16:45 UTC, Anton Pastukhov wrote: On Tuesday, 28 February 2017 at 17:16:43 UTC, Daniel Kozák wrote: V Tue, 28 Feb 2017 15:15:00 + Anton Pastukhov via Digitalmars-d-learnnapsáno: I can't see the logic in AA foreach order. Consider this code: ... Output: three two one four I was sure output should be one two three four https://forum.dlang.org/post/xbanhtkvrizyqjcib...@forum.dlang.org Thank you for the link, it was informative reading. It's a pity that still there is no ordered AA at least as a library type. Ordered AA isn't that common a use case, and it's not without overhead. You essentially need to store an array of keys that define iteration order, which requires extra memory allocations (and, depending on implementation, may slow down iteration as well). I come from a Ruby background, so I have found key order useful in the past, but in most cases I probably could've gotten by just fine with an array or set of element pairs. Introduction of a more convenient tuple type into D might make something like this easier.
Re: Getting nice print of struct for debugging
On Saturday, 25 February 2017 at 01:27:09 UTC, Minty Fresh wrote: On Wednesday, 22 February 2017 at 11:18:15 UTC, Martin Tschierschke wrote: [...] Since structs are Plain-old Data and don't do inheritance, the best option is a template mixin. ie. template mixin PrettyPrint { string toString() { // . . . } } From there, you can mix it into any struct you want. struct MyStruct { mixin PrettyPrint; } If you're familiar with Rails, this is similar to a Concern. Errata on that. Should actually be declared as: mixin template PrettyPrint() This is why I shouldn't make posts from my phone.
Re: Getting nice print of struct for debugging
On Wednesday, 22 February 2017 at 11:18:15 UTC, Martin Tschierschke wrote: On Tuesday, 21 February 2017 at 14:02:54 UTC, Jacob Carlborg wrote: [...] Yes, this works, I would say this is the simplest: MyStruct s; foreach (index, name ; FieldNameTuple!MyStruct) writefln("%s: %s", name, s.tupleof[index]); If you want something more close to "send" in Ruby, you need to use a string mixin, like this: foreach (name ; FieldNameTuple!MyStruct) writefln("%s: %s", name, mixin("s." ~ name)); The string mixin example works for methods, opDispatch and similar as well. The tupleof example, the first one, works only for fields. Exactly what I was looking for, **thank you!** Both ways of accessing the struct elements are very interesting, giving an impression what is possible with D. Is it possible to overwrite "toString" for all structs in one step? Regards mt. Since structs are Plain-old Data and don't do inheritance, the best option is a template mixin. ie. template mixin PrettyPrint { string toString() { // . . . } } From there, you can mix it into any struct you want. struct MyStruct { mixin PrettyPrint; } If you're familiar with Rails, this is similar to a Concern.
Allocators and Containers
A lot of the usefulness of the std.experimental.allocators module is lost because no other part of the stdlib actually ties into the functionality provided by it. For example, the Array type defined in std.container relies on malloc() directly, so if you wanted to use a type to replace built-in arrays with a custom allocator, you'd need to implement your own container type. Would it make sense to allow the std.container types to accept IAllocator instances, and to allow custom allocators? (Using Mallocator by default.)
Re: Convert struct to set of fields and pass it's to constructor
On Wednesday, 1 February 2017 at 13:37:27 UTC, Suliman wrote: Class constructor accept only set if fields like this(string login, string pass) Can I create structure, fill it, and than pass to constructor? Like this: ``` import std.stdio; struct ConnectSettings { string login; string pass; }; ConnectSettings cs; void main() { cs.login = "admin"; cs.pass = "mypass"; } ``` and than pass to constructor it's like: `... new SomeClass(cs)` I tried, but get error, that ctor accept only fields list. Can I unroll struct to it? tupleof is probably what you're looking for. ie. new SomeClass(cs.tupleof); That said, why not have the constructor accept the struct as a parameter?
Re: Dlang dynamic compilation
On Monday, 21 November 2016 at 18:59:17 UTC, Ivan Butygin wrote: Hacked ldc sources are here: https://github.com/Hardcode84/ldc/tree/runtime_compile Very cool. Although @runtimeCompile does peeve me, as it seems unnecessarily verbose (being longer than any other attribute, I think). I'd have gone with @rtc or similar so as not to clutter function and variable declarations, but those are just my thoughts on language readability.
Re: Overloading relational operators separately; thoughts?
On Saturday, 1 October 2016 at 17:53:44 UTC, Russel Winder wrote: On Sat, 2016-10-01 at 14:55 +, Chris Wright via Digitalmars-d wrote: Groovy doesn't allow you to overload comparison operators individually, and probably most JVM languages likewise. This is to retain compatibility with Java, which has `.compareTo()` instead of `isLessThan()` etc. Yes it does. http://groovy-lang.org/operators.html There is *also* compareTo. Ruby allows you to override individual comparison operators, with a special operator `<=>` for combined comparisons. Nim lets you overload arbitrary operators and create your own; some old discussions suggest that the Comparable type is based on `<` alone. Groovy also supports the spaceship operator. `<=>` exists for the general case, which is what `opCmp` covers in D. Overloading each relational operator individually is made possible to address any sort of special cases. The issue being, in D there is no room for any manner of special case.
Re: Overloading relational operators separately; thoughts?
On Friday, 30 September 2016 at 23:31:19 UTC, Sai wrote: Genuine question: In the post Java languages, how many languages allowed unrestricted operator overloading and did that cause any similar mess? Thanks in advance for any answers. Although there maybe a bit of bias here, but I'd say Rub does it quite well (although the syntax for unary operator overloads is a bit bizarre), since I work with the language on a daily basis. But going a step further there's languages like Haskell that allow defining completely new operators. Both of the aforementioned have amassed an exceedingly large following at this point.
Re: Overloading relational operators separately; thoughts?
On Friday, 30 September 2016 at 22:38:07 UTC, Walter Bright wrote: On 9/30/2016 1:14 PM, Minty Fresh wrote: Metathesiophobia Repeatedly suggesting people who don't agree with you have mental disorders does not advance your case and is not appreciated here. Metathesiophobia is not a mental disorder, it's a phobia. There's quite a bit of distinction there. Specifically it's an ungrounded fear or dislike of change. It's altogether not uncommon, actually. A more productive way forward is for you (and those who agree with you) to prepare a formal DIP and submit it. It's the way significant language change proposals are done. That was sort of the initial intent of this thread. To test the waters and see if the idea would have support. But it seems the community is extremely torn on the matter.
Re: Overloading relational operators separately; thoughts?
On Friday, 30 September 2016 at 19:46:35 UTC, bachmeier wrote: Claiming that operator overloading only applies to a specific user-defined type makes it worse. Having it work one way for three types, a different way for four other types, and a third way for yet another type doesn't sound like a minor thing. But operators already behave in different way for different types. Built-in types inclusive. The most trivial and nit-picky difference would be between integer types and floating point types. ie. Division between two integers yields an integer, division between two floats yields a float, but then division between an integer and a float also yields a float. Alternatively, the bit-shift operators `<<` and `>>` don't function at all for floats. But then we have also wonderful floating point values like `NaN` and `Infinity` for which arithmetic and relational operators behave differently altogether. Another would static arrays, versus dynamic arrays, versus associative arrays. The first two support concatenation via `~`, only the second supports in-place concatenation `~=`, and the last has no notion of concatenation at all. A counter argument that might be raised is that those are different types altogether. They are intended to behave in different ways entirely. Completely different data structures. Their similarities are only superficial. And such a counter argument would be absolutely correct. Markedly so. They are completely different types. The same is true of user-defined types. Their behavior should not be equated to (nor expected to be like) the behaviors of types they only resemble superficially. But have fun debating design decisions that were made long ago and aren't going to change. That's exactly the kind of decision making you see in C++ and PHP. Metathesiophobia would be one way of describing it. Stubborn blindness to real world usage is more contextually appropriate though, I feel.
Re: Overloading relational operators separately; thoughts?
On Friday, 30 September 2016 at 00:50:54 UTC, Jonathan M Davis wrote: Except that it kind of is. It's an example of a language allowing you to mess with too much and make it so that it doesn't function as expected, which is what happens when you overload operators to act in a way inconsistent with how they work with the built-in types. The perl example is more extreme, but the point still stands that having normal, common constructs operate in a way that's inconsistent with how they normally work tends to make code harder to read and maintain. Certainly, it can result in very unexpected behavior when mixing it with generic code that uses those operations. - Jonathan M Davis It's up to the developer to ensure that their code works correctly with existing facilities, not the language. I can already write code that will work in amazing and ridiculous ways with generic code in the standard library. It does not follow that the language is responsible or at fault for the code behaving in ways that are unexpected. Furthermore, it's completely reasonable to write code that works with the generic facilities in the standard library, even if it doesn't behave exactly like a built in type. ie. foo.reduce!"a + b"; // => produces an integer bar.reduce!"a + b"; // => produces an AST node So long as the types produced by the operation are correct, this will work just fine.
Re: Overloading relational operators separately; thoughts?
On Thursday, 29 September 2016 at 22:27:50 UTC, bachmeier wrote: You're looking for https://www.perl.org/ That's a highly viable language, where you can do things like bury $[ = 1 somewhere in your code to change from 0-indexing to 1-indexing of arrays. They take pride in unpredictable, unreadable code. This is not at all relevant to the current argument.
Re: Overloading relational operators separately; thoughts?
On Thursday, 29 September 2016 at 19:39:35 UTC, Jonathan M Davis wrote: The language can't stop you from doing at least some arbitrary stuff with them (like making + do subtraction), but the whole goal was for user-defined types to be able to act like the built-in types, and as such, it would make no sense to alter them towards being treated like symbols that you can do whatever you want with. Having `+` do subtraction isn't something you'd normally see. It's not a use case that would normally exist. Having `+` do addition, but do so in a database layer is a use case that actually may exist. The operator still behaves like a built-in type. It may perform addition as part of a SQL query, for example. Whether the expression `a + b` is translated into machine language, or translated into SQL, both still perform addition. A value represented by `a` is added to a value represented by `b`. Whether `a` and `b` are variables in D, or columns in a database table is irrelevant. And as it stands, D can already do this. It's the inability to perform an equivalent action for the expression `a > b`.
Re: Overloading relational operators separately; thoughts?
On Thursday, 29 September 2016 at 19:11:55 UTC, pineapple wrote: Relinquish the notion that you or anyone can have the slightest idea what any language feature is "supposed to mean and be used for". Basically what led to D's CTFE implementation in the first place, IIRC.
Re: Overloading relational operators separately; thoughts?
On Thursday, 29 September 2016 at 18:07:37 UTC, Russel Winder wrote: On Thu, 2016-09-29 at 10:52 -0700, Walter Bright via Digitalmars-d wrote: On 9/29/2016 9:41 AM, Sai wrote: > > If I understand the issue correctly, one will not be able to > overload <=, >, etc > for symbolic math, like CAS (mimicking mathematica for > example), > how can I do it > now? a.isLessThan(b) How wonderfully Java. Personally, I'm amused because this implies the prospect of: a.isGreaterThanOrEqualTo(b) I mean, there is an acceptable level of verbosity. This is not it.
Re: Overloading relational operators separately; thoughts?
On Thursday, 29 September 2016 at 12:54:54 UTC, Jacob Carlborg wrote: BTW, there's a CTFE parser generator for D around somewhere. And that will handle all that the DMD parser does? I don't think so. I agree with this entirely. Lest you have an entire D compiler implemented in CTFE (reductio ad absurdum), you're working with a limited subset of the language, and pose additional challenges for a developer trying to debug. Not to mention that string mixins render IDE features like code completion and error highlighting essentially unusable.
Re: Overloading relational operators separately; thoughts?
On Thursday, 29 September 2016 at 11:29:55 UTC, Russel Winder wrote: However, this has come up many times, and every time Walter says "no, it's wrong". Whilst the C++ iostreams << may have problems, using this as a single point argument as to why overloading fails in all other cases except numeric arithmetic is bad philosophy. In my view this is holding D back. To add some thoughts to this, The use of << being bad is purely a matter of opinion. If you believe that << is to only be used for bit-shifting operations, you might hold the view that it is bad. On the other hand, if you come from a background like Haskell or Ruby, you might have a very different opinion. ie. In Ruby, << is named the shovel operator. It's uses are things like appending an element into an Array. Hence, a less opinionated point is necessary here.
Re: Overloading relational operators separately; thoughts?
On Thursday, 29 September 2016 at 04:15:32 UTC, Walter Bright wrote: On 9/28/2016 1:40 PM, Timon Gehr wrote: What's wrong with that usage? Because then something other than comparison is happening with <=, <, >, >= and there'll be nothing in the code to give the user a hint. There's also nothing to give the user a hint that binary arithmetic operators may also not do what they expect them to do. Going further, there may be nothing to give the user a hint that a named function doesn't to what its name suggests. All of the above are shortcomings in documentation, or short comings in implementation. Even with the current system of using `opCmp`, it's still possible to implement these operators such that they behave in a way that would confound the user (ie. have their results be nondeterministic, external side effects, etc.) D has many very powerful modeling abilities, but so far we've tried to stay away from things that make context-free user understanding of code unduly difficult. It should not be necessary to use an IDE to understand code. No, you're right. It's not the responsibility of the IDE to perform such tasks. It's the responsibility of the documentation. D is already is such a state the language is difficult for a context-free user without access to documentation. Even the standard library. Especially the standard library. Things like `.each` in std.algorithm returning void, whereas the bizarrely named `.tee` in std.range actually retuning the input range. Things like the `SList` and `DList` types defined in std.container requiring explicit initialization to work. Things like the behavior and semantics of type tuples (or alias lists). Things like the differences between `.byLine` vs `.byLineCopy` in std.stdio. All of these rely on the developer having documentation. There's no way around it. D as a language is already way too complex to do anything without it. This applies to operator overloads just like everything else. They're just syntactic sugar for functions. Documenting their behavior is just as necessary.
Re: Module names shadowing defined functions/templates.
On Thursday, 29 September 2016 at 02:26:15 UTC, Joakim wrote: I ran into this too, it is annoying. I think you're supposed to use different names. It's a rather painful limitation if that were the case. Going with the example I gave, what would an alternative name for the module be? All it's public members are named `leastsq`. While I can imagine there are technical challenges that have caused this issue to be the way it is, it's still a pretty major flaw to try to work around. Working around shortcomings of a language is never a good place to be in.
Re: Module names shadowing defined functions/templates.
As an addendum to the above, the error message I posted was from the overload that takes a delegate as a runtime parameter. Trying to pass template arguments just gives you: Error: template instance leastsq!((p) => p) leastsq is not a template declaration, it is a import
Module names shadowing defined functions/templates.
I ran into this issue just recently when trying to write a least-squares optimization function. Notably, module leastsq; T[] leastsq(alias func, T)(T[] vec, . . .) { . . . } It becomes impossible to import and call this template function from outside the module it's declared in. Trying to do so just yields: Error: function expected before (), not module leastsq of type void This is really inconvenient. `leastsq` has a very long and implementation, most of which is not a public API. It makes sense to put it into its own module because it and all of the functions it uses internally are some 1000 lines long. I don't really know of any other language that faces this limitation.
Re: Overloading relational operators separately; thoughts?
On Wednesday, 28 September 2016 at 20:40:49 UTC, Timon Gehr wrote: This is not surprising. C++ has no good options. This is further made worse by some C++'s more inane design decisions (ie. allowing overloading of the comma operator).
Re: Overloading relational operators separately; thoughts?
On Wednesday, 28 September 2016 at 20:16:08 UTC, Walter Bright wrote: To reiterate, operator overloading exists in D to support the inclusion of arithmetic library types. Any other purpose is discouraged, and that includes expression templates and things like << for iostreams. It seeds rather harsh to discourage every possible use case of a feature sans one, simply because one does not agree with the others.
Re: Overloading relational operators separately; thoughts?
On Wednesday, 28 September 2016 at 04:02:59 UTC, Walter Bright wrote: The use of them to create DSLs (a technique called "expression templates" in C++) is discouraged in D, for several reasons. The recommended way to create DSLs in D is to parse strings using CTFE. I don't really come from a C++ background. Actually, I have a strong distaste for the language. Professionally, I word with Ruby. Again, string DSLs face a number of issues. A few that come to mind are: 1. A parser + code generator must be implemented, which is a lot of additional work. 2. The quality and precision of error messages degrades. 3. You loose the ability to perform actions like making declarations within the context of the DSL (ie. assigning a commonly re-used expression to a variable), unless your DSL is turing complete. An excellent example of that is the std.regex package. You know, if someone had managed to implement a regex DSL using operator overloading, something must have gone _terribly_ wrong. Regex is traditionally done in strings, lest the language supports regex literals.
Re: Overloading relational operators separately; thoughts?
On Wednesday, 28 September 2016 at 03:12:05 UTC, Jonathan M Davis wrote: On Wednesday, September 28, 2016 01:18:58 Minty Fresh via Digitalmars-d wrote: Basically, having them be overloaded separately is error-prone, and it leads to folks overloading them in ways that have nothing to do with what they mean for the built-in types, which makes code harder to read and maintain. D has a concatenation operator specifically because Walter thought that it was horrible to use + for concatenation. If you want to write DSLs, then use strings and mixins. D gives you a _lot_ of power in that area, and it avoids the problems associated with making overloaded operators do things other than what those operators are normally intended to do. With strings, you can make your DSL look however you want - even doing stuff like using various Unicode symbols as operators if you want to. Even with how C++ overloads operators, overloading operators gives you fairly limited options with what you can do with a DSL, whereas you have full freedom with strings - and without the problems that come with trying to make your DSL look like normal D code. - Jonathan M Davis Using strings and mixins does have quite a number of downsides. The additional work required to past the DSL aside, you also usually lose the scope in which things are declared (especially if you wish to reference or declare variables/functions/other constructs within your DSL), error reporting becomes much less precise, and the transition between the outer code and the inner DSL becomes jarring (especially in terms of syntax highlighting). That said, I love the fact D has a separate operator for concatenation. It's extremely useful to not have that ambiguity. Another thought is, operators not behaving as expected doesn't strike me as a failure of the language, given the language supports operator overloading. It's a failure in documentation to explain what the operators are intended to do, or a failure in implementation to behave as they should. Lastly, if operators are intended to behave so strictly, why does this not extend then to binary arithmetic operators (+, -, *, /, %, etc.) They don't follow the same rules as the binary relational operators, after all.
Overloading relational operators separately; thoughts?
Currently, D offers fine grained overloading for most of the unary and arithmetic binary operators, but at some point a decision was made to lump together all of the relational operators (and if necessary, the equality operators) into a single function `opCmp`. And while it does add a lot of convenience and consistency to how operators behave, it does also put a lot of limitations on what they can do. For example, it's not currently possible to implement comparison operators that would behave lazily and only compute a certain value once a function call forces the computation. Similarly, it's not possible to construct a DSL that would produce code or a query in another language, by returning values behave like AST nodes rather than actually performing a comparison. ie. table.users .where!((users) => users.joined_on >= 3.days.ago) .joins(table.posts) .on!((posts, users) => posts.user_id == users.id) .limit(10) .toSql; It's a little odd to me that D puts so little focus on DSLs, since language features like template constraints, `opDispatch`, and even the fact that binary operators are overloadable via a single templated function are all very useful tools for implementing them. So, I'm just interested in other people's thoughts are on the subject, and whether there are any plans to allow overloading these operators separately.