digitalmars.D - Overloading relational operators separately; thoughts?
- Minty Fresh (30/30) Sep 27 2016 Currently, D offers fine grained overloading for most of the
- Jonathan M Davis via Digitalmars-d (16/19) Sep 27 2016 Basically, having them be overloaded separately is error-prone, and it l...
- Minty Fresh (21/41) Sep 27 2016 Using strings and mixins does have quite a number of downsides.
- Jonathan M Davis via Digitalmars-d (20/25) Sep 27 2016 It's not possible in the general case to define the arithmetic operators...
- Chris Wright (6/16) Sep 28 2016 Specifically for making efficient programs. Increment, decrement, and
- Guillaume Boucher (5/10) Sep 28 2016 Only for BigInts you need those three. For ints decrement is not
- pineapple (25/52) Sep 28 2016 I agree that opCmp has the benefit of unambiguity, but I still
- pineapple (16/16) Sep 28 2016 I'd also like to point out a generally sound design principle:
- Chris Wright (16/20) Sep 28 2016 What happens with this?
- Walter Bright (11/13) Sep 27 2016 The limitations are deliberate based on the idea that comparison operato...
- Matthias Bentrup (10/14) Sep 28 2016 In Mathematics the comparison operators are also commonly used
- Timon Gehr (5/13) Sep 28 2016 Yes it does.
- Walter Bright (6/13) Sep 28 2016 I'm aware of the limitation, and a fair amount of thought was given on i...
- Timon Gehr (20/36) Sep 28 2016 The restrictions enforce that <= computes a boolean result. "less than
- John Colvin (3/12) Sep 28 2016 Thanks for expressing this so clearly. This is exactly the sort
- Walter Bright (12/24) Sep 28 2016 Yet this "obviously bad" idea regularly resurfaces as a cool use of expr...
- pineapple (14/20) Sep 28 2016 This is an obsolete way of thinking about operators. Operator
- Russel Winder via Digitalmars-d (27/50) Sep 29 2016 Definitely, yes.=C2=A0
- Minty Fresh (12/17) Sep 29 2016 To add some thoughts to this,
- Russel Winder via Digitalmars-d (27/48) Sep 29 2016 But, but, but, << means very much less than, everyone knows this. What
- pineapple (4/18) Sep 29 2016 Reminds me of this -
- Minty Fresh (5/9) Sep 28 2016 It seeds rather harsh to discourage every possible use case of a
- Timon Gehr (4/32) Sep 28 2016 What's wrong with that usage? (This is NOT expression templates.)
- Minty Fresh (3/4) Sep 28 2016 This is further made worse by some C++'s more inane design
- Walter Bright (11/13) Sep 28 2016 Because then something other than comparison is happening with <=, <, >,...
- Minty Fresh (30/39) Sep 28 2016 There's also nothing to give the user a hint that binary
- Mike Parker (22/25) Sep 28 2016 I disagree with this. Operators are different in that the symbols
- Jonathan M Davis via Digitalmars-d (30/35) Sep 28 2016 [snip]
- Timon Gehr (10/28) Sep 29 2016 Actually, comparison is precisely what is happening. The hint about what...
- Chris Wright (5/15) Sep 29 2016 To take it the other way, D could enforce that the return type of
- Timon Gehr (3/18) Sep 30 2016 Certainly.
- Timon Gehr (15/20) Sep 30 2016 On a related note:
- Andrei Alexandrescu (2/24) Sep 30 2016 That looks awfully cool! -- Andrei
- Timon Gehr (2/30) Sep 30 2016 [my code here]
- Russel Winder via Digitalmars-d (29/36) Sep 29 2016 This is a very "tunnel vision" view of programming language and the way
- Martin Nowak (8/31) Oct 01 2016 The fact that it's not possible to overload < but have to use the
- Andrei Alexandrescu (4/8) Oct 01 2016 I've also been often annoyed by having to write
- Andrei Alexandrescu (5/13) Oct 01 2016 Apparently in dmd the generated code is less efficient:
- pineapple (10/30) Oct 01 2016 On Saturday, 1 October 2016 at 11:53:07 UTC, Andrei Alexandrescu
- Minty Fresh (18/23) Sep 28 2016 I don't really come from a C++ background. Actually, I have a
- Jacob Carlborg (19/27) Sep 28 2016 If that is not allowed, why is this allowed:
- Walter Bright (13/23) Sep 29 2016 I.e. you can overload '+' to do bad things. Yes, you can, and as I repli...
- pineapple (33/48) Sep 29 2016 This is not an argument to justify adding just any feature, it's
- Jacob Carlborg (4/31) Sep 29 2016 Well said.
- Jacob Carlborg (37/53) Sep 29 2016 You're using the same justification when rejecting most feature requests...
- Minty Fresh (8/11) Sep 29 2016 I agree with this entirely. Lest you have an entire D compiler
- Sai (5/11) Sep 29 2016 If I understand the issue correctly, one will not be able to
- Walter Bright (2/5) Sep 29 2016 a.isLessThan(b)
- Russel Winder via Digitalmars-d (13/23) Sep 29 2016 How wonderfully Java.
- Minty Fresh (5/19) Sep 29 2016 Personally, I'm amused because this implies the prospect of:
- Jonathan M Davis via Digitalmars-d (7/26) Sep 29 2016 Then you could always do something like a.myOp!"<"(b) and a.myOp!">="(b)...
- Matthias Bentrup (4/11) Sep 29 2016 Also with mixins and a CTFE D parser you could replace the
- pineapple (13/16) Sep 29 2016 This is not a valid argument because what an operator is
- Minty Fresh (3/6) Sep 29 2016 Basically what led to D's CTFE implementation in the first place,
- Jonathan M Davis via Digitalmars-d (37/53) Sep 29 2016 Every language feature is designed with a purpose. Sometimes that purpos...
- Minty Fresh (15/21) Sep 29 2016 Having `+` do subtraction isn't something you'd normally see.
- pineapple (21/33) Sep 29 2016 I repeat: Your thinking like this limits D's viability for
- Jonathan M Davis via Digitalmars-d (54/87) Sep 29 2016 Except that the limits aren't arbitrary. Walter designed D's overloaded
- bachmeier (5/7) Sep 29 2016 You're looking for https://www.perl.org/ That's a highly viable
- Minty Fresh (2/6) Sep 29 2016 This is not at all relevant to the current argument.
- bachmeier (2/8) Sep 29 2016 I see
- Jonathan M Davis via Digitalmars-d (11/17) Sep 29 2016 Except that it kind of is. It's an example of a language allowing you to
- Chris Wright (6/10) Sep 29 2016 The perl example is a line of code buried somewhere that changes the
- bachmeier (12/17) Sep 30 2016 I was responding to someone that wrote: "I also have the presence
- Minty Fresh (30/36) Sep 30 2016 But operators already behave in different way for different
- Walter Bright (6/7) Sep 30 2016 Repeatedly suggesting people who don't agree with you have mental disord...
- pineapple (15/18) Sep 30 2016 A good idea.
- Russel Winder via Digitalmars-d (20/25) Sep 30 2016 But is the effort worth it? Will the DIP and PR be assessed? Does it
- Minty Fresh (8/16) Oct 01 2016 Metathesiophobia is not a mental disorder, it's a phobia. There's
- pineapple (7/12) Sep 30 2016 Which language is more widely used? D or Perl?
- Jonathan M Davis via Digitalmars-d (9/21) Sep 30 2016 perl is always widely considered to be a horrible language even if it is
- Timon Gehr (3/7) Sep 30 2016 OTOH, feet are useless if you are not allowed to walk (even if you
- Dominikus Dittes Scherkl (32/54) Sep 30 2016 But operator overloading doesn't increase the language
- Timon Gehr (32/74) Sep 30 2016 There's a continuum here. Another data point:
- Russel Winder via Digitalmars-d (56/82) Sep 30 2016 Expressiveness is not a metric, there isn't even a partial order, it is
- Minty Fresh (16/27) Sep 30 2016 It's up to the developer to ensure that their code works
- Jonathan M Davis via Digitalmars-d (24/30) Sep 30 2016 Of course, you can write code that behaves badly. There's no way that th...
- pineapple (25/33) Sep 30 2016 In your arguments in favor of this limitation of operator
- Chris Wright (18/27) Oct 01 2016 More like: this is the common use case, so let's try to make that as
- Sai (7/8) Sep 30 2016 I understand the concern of possible mess due to unrestricted use
- Timon Gehr (2/4) Sep 30 2016 C++ does it in std.
- Russel Winder via Digitalmars-d (26/29) Sep 30 2016 It is not feasible to provide a count, as there is always another
- Chris Wright (8/10) Oct 01 2016 Groovy doesn't allow you to overload comparison operators individually,
- Russel Winder via Digitalmars-d (15/26) Oct 01 2016 Yes it does. =C2=A0http://groovy-lang.org/operators.html
- Minty Fresh (6/24) Oct 02 2016 `<=>` exists for the general case, which is what `opCmp` covers
- Minty Fresh (8/12) Oct 01 2016 Although there maybe a bit of bias here, but I'd say Rub does it
- Timon Gehr (2/14) Sep 29 2016 Not really, but it's annoying.
- Jacob Carlborg (6/30) Sep 27 2016 I completely agree. Or we could go with an even more general approach:
- rikki cattermole (43/43) Sep 29 2016 Me and Cauterite were toying with the idea of AST macros but in a
- Jacob Carlborg (7/50) Sep 29 2016 Hmm, I find this to be somewhat difficult to follow. You get the AST as
- rikki cattermole (29/90) Sep 29 2016 I'll expand on what I wrote above.
- Atila Neves (5/14) Oct 02 2016 opCmp was a good idea.
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.
Sep 27 2016
On Wednesday, September 28, 2016 01:18:58 Minty Fresh via Digitalmars-d wrote: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.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
Sep 27 2016
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 DavisUsing 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.
Sep 27 2016
On Wednesday, September 28, 2016 03:28:50 Minty Fresh via Digitalmars-d wrote: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.It's not possible in the general case to define the arithmetic operators as functions of each other. They actually need to be defined separately in order to work. The comparison operators don't have that problem. And in the cases where the arithmetic operations are essentially being passed on to a member variable such that it's just the operator itself that's changing, and the code is otherwise the same, the fact that opBinary takes a string for the operator makes it trivial to use string mixins so that you only need one function body for all of the operators, whereas in the cases where you can't do that (e.g. the operation involves multiple member variables), you can declare separate functions. The increment and decrement operators are in a similar boat to the comparison operators in that post and pre can be derived from a single function. So, it's not just the comparison operators that got combined. In the cases where it made sense to combine operators, they were combined, and in the cases where it didn't make sense, they weren't. It would be nice if more could be combined, but most of them actually need to be separate to work. Fortunately though, some of them can be combined, and those were combined, which makes operator overloading in D easier and less error-prone. - Jonathan M Davis
Sep 27 2016
On Tue, 27 Sep 2016 23:05:54 -0700, Jonathan M Davis via Digitalmars-d wrote:On Wednesday, September 28, 2016 03:28:50 Minty Fresh via Digitalmars-d wrote:Specifically for making efficient programs. Increment, decrement, and test for equality is sufficient mathematically, but we want programs that terminate in our lifetimes. </pedantry>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.It's not possible in the general case to define the arithmetic operators as functions of each other. They actually need to be defined separately in order to work.
Sep 28 2016
On Wednesday, 28 September 2016 at 14:27:58 UTC, Chris Wright wrote:Increment, decrement, and test for equality is sufficient mathematically, but we want programs that terminate in our lifetimes. </pedantry>Only for BigInts you need those three. For ints decrement is not needed. And for most other data types increment/decrement is not sufficient, e.g. for reals or any kind of vectors/matrices.
Sep 28 2016
On Wednesday, 28 September 2016 at 03:28:50 UTC, Minty Fresh wrote: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.I agree that opCmp has the benefit of unambiguity, but I still think Minty makes very good points. I think the cleanest possible solution would be to allow comparison operators to be overridden with opBinary and opBinaryRight, as well, but use opCmp and opEquals instead if they exist. I can't think of any way this would break existing code. On Wednesday, 28 September 2016 at 09:48:48 UTC, Matthias Bentrup wrote:In Mathematics the comparison operators are also commonly used for semi orders, which cannot be implemented by opCmp, because opCmp has no way to indicate that two values are incomparable. Interestingly the floating point types are semi ordered (due to NaNs), and for those D has some (non-overridable and deprecated) operators like !<, which would be easily extendable to any semi order, whereas the suggested replacement (i.e. test for NaNs manually) works only on floats.It's probably a terrible idea, but I'd love if those FP comparison operators would be de-deprecated and made possible to overload using opBinary. On Wednesday, 28 September 2016 at 06:05:54 UTC, Jonathan M Davis wrote:The increment and decrement operators are in a similar boat to the comparison operators in that post and pre can be derived from a single function. So, it's not just the comparison operators that got combined.Incidentally, I'm a little surprised and disappointed that D doesn't allow pre- and postfix operators to be separately overloaded. Postfix operators should default to their current behavior, where `x<op>` is the same as `auto t = x; x = <op>x; return t;` where prefix unary <op> is defined, but I also think it'd be fantastic if we introduced an opUnaryPostfix override. (And should that be done, for the sake of clarity, it might be a good idea deprecate usage of opUnary in favor of calling the method opUnaryPrefix.)
Sep 28 2016
I'd also like to point out a generally sound design principle: Give the programmer as much power and flexibility as possible - but don't forget to provide tools for simplifying common use cases, and don't forget to define sensible defaults. It makes a lot of sense that opCmp and opEquals exist, they fit the by-far-most-common use case perfectly, but they aren't always flexible enough for what the programmer wants to do. What if comparison operators should return something other than booleans? What if `!=` should be implemented differently from `==`? These overrides great tools to have, but it would be better if they weren't the only options we had. Similarly, it makes a lot of sense that postfix operators are rewritten in terms of prefix operators, but that's not always flexible enough for what the programmer wants to do. It's a great default to have, but it would be better if we also had the option to define our own distinct behaviors for postfix operators.
Sep 28 2016
On Wed, 28 Sep 2016 10:06:43 +0000, pineapple wrote:I think the cleanest possible solution would be to allow comparison operators to be overridden with opBinary and opBinaryRight, as well, but use opCmp and opEquals instead if they exist. I can't think of any way this would break existing code.What happens with this? struct MyInt { int value; MyInt opBinary(string op)(MyInt other) { return MyInt(mixin("value " ~ op ~ " other.value")); } } Obvious pattern for wrapping a value. Comparisons used to be unsupported, producing an appropriate error message: Error: need member function opCmp() for struct MyInt to compare Now they produce a different, opaque error message, which will have to be created, but the current equivalent is: Error: recursive opCmp expansion That's not a breakage, but it is an unfortunate direction for the quality of error messages.
Sep 28 2016
On 9/27/2016 6:18 PM, Minty Fresh wrote: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.The limitations are deliberate based on the idea that comparison operators need to be consistent and predictable, and should have a close relationship to the mathematical meaning of the operators. Overloading <= to mean something other than "less than or equal" is considered poor style in D, and the same goes for the other arithmetic operators. 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. An excellent example of that is the std.regex package. There are no plans to change this.
Sep 27 2016
On Wednesday, 28 September 2016 at 04:02:59 UTC, Walter Bright wrote:The limitations are deliberate based on the idea that comparison operators need to be consistent and predictable, and should have a close relationship to the mathematical meaning of the operators.In Mathematics the comparison operators are also commonly used for semi orders, which cannot be implemented by opCmp, because opCmp has no way to indicate that two values are incomparable. Interestingly the floating point types are semi ordered (due to NaNs), and for those D has some (non-overridable and deprecated) operators like !<, which would be easily extendable to any semi order, whereas the suggested replacement (i.e. test for NaNs manually) works only on floats.
Sep 28 2016
On 28.09.2016 11:48, Matthias Bentrup wrote:On Wednesday, 28 September 2016 at 04:02:59 UTC, Walter Bright wrote:Yes it does. float opCmp(S rhs){ return float.nan; // incomparable }The limitations are deliberate based on the idea that comparison operators need to be consistent and predictable, and should have a close relationship to the mathematical meaning of the operators.In Mathematics the comparison operators are also commonly used for semi orders, which cannot be implemented by opCmp, because opCmp has no way to indicate that two values are incomparable. ...
Sep 28 2016
On 9/28/2016 2:48 AM, Matthias Bentrup wrote:In Mathematics the comparison operators are also commonly used for semi orders, which cannot be implemented by opCmp, because opCmp has no way to indicate that two values are incomparable. Interestingly the floating point types are semi ordered (due to NaNs), and for those D has some (non-overridable and deprecated) operators like !<, which would be easily extendable to any semi order, whereas the suggested replacement (i.e. test for NaNs manually) works only on floats.I'm aware of the limitation, and a fair amount of thought was given on it, but the solution used generally for unordered is to test for it separately, and people seem happy with it. The !<, etc., operators have been an utter failure (not a failure technically, but people found them hopelessly confusing and would not use them).
Sep 28 2016
On 28.09.2016 06:02, Walter Bright wrote:On 9/27/2016 6:18 PM, Minty Fresh wrote:The restrictions enforce that <= computes a boolean result. "less than or equal" is not necessarily the same as "decide /now/ whether this is less than or equal and give me a boolean". The restriction is annoying if you are implementing e.g. symbolic algebra. opCmp is a good thing to have for the common case, but why disable opBinary?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.The limitations are deliberate based on the idea that comparison operators need to be consistent and predictable, and should have a close relationship to the mathematical meaning of the operators. Overloading <= to mean something other than "less than or equal" is considered poor style in D, and the same goes for the other arithmetic operators. ...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.One anecdote: In the big-O library discussion, my initial proposal relied on string parsing. Andrei promptly criticized this and used operator overloading instead.An excellent example of that is the std.regex package. ...It's actually a bad example, because it is irrelevant: it is obviously a bad idea to implement regex using operator overloading, because the regex operators have no D equivalent. Assume I have two symbolic expressions a and b: Expression a=variable("a"), b=variable("b"); Why should I be allowed to do auto c = a + b; // symbolic value a + b but not auto d = a <= b; // symbolic value a <= b The string parsing approach is not useful here: how do I use existing expressions that are accessible in the scope to build new expressions?
Sep 28 2016
On Wednesday, 28 September 2016 at 13:58:35 UTC, Timon Gehr wrote:Assume I have two symbolic expressions a and b: Expression a=variable("a"), b=variable("b"); Why should I be allowed to do auto c = a + b; // symbolic value a + b but not auto d = a <= b; // symbolic value a <= b The string parsing approach is not useful here: how do I use existing expressions that are accessible in the scope to build new expressions?Thanks for expressing this so clearly. This is exactly the sort of thing I want to be able to do.
Sep 28 2016
On 9/28/2016 6:58 AM, Timon Gehr wrote:Yet this "obviously bad" idea regularly resurfaces as a cool use of expression templates and respected people in the industry like it and advocate it.An excellent example of that is the std.regex package.It's actually a bad example, because it is irrelevant: it is obviously a bad idea to implement regex using operator overloading, because the regex operators have no D equivalent.Assume I have two symbolic expressions a and b: Expression a=variable("a"), b=variable("b"); Why should I be allowed to do auto c = a + b; // symbolic value a + b but not auto d = a <= b; // symbolic value a <= bBecause there is no way to stop the former but still have operator overloading.The string parsing approach is not useful here: how do I use existing expressions that are accessible in the scope to build new expressions?You seem to be asking for expression templates. They do actually work in D, but I recommend against them. 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. AST macros are an alternative to expression templates. Having AST macros has been proposed before multiple times, and has been debated at length. I haven't seen any new information that would justify reopening the issue.
Sep 28 2016
On Wednesday, 28 September 2016 at 20:16:08 UTC, Walter Bright wrote:Because there is no way to stop the former but still have operator overloading. 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.This is an obsolete way of thinking about operators. Operator overloading exists to make the programmer's life easier, and limiting the ways in which a valuable tool can be used drives people to languages which allow them to be more expressive. For my job I write Python. We use a database layer called sqlalchemy that allows us to express queries by writing, for example, `session.query(some_table).filter(row1 == row2)` and I cannot begin to express how useful this is when writing code, when maintaining code, and when attempting to understand code that someone else wrote. The objective should never be to stop the programmer from doing something because you personally dislike the practice.
Sep 28 2016
On Wed, 2016-09-28 at 20:30 +0000, pineapple via Digitalmars-d wrote:On Wednesday, 28 September 2016 at 20:16:08 UTC, Walter Bright=C2=A0 wrote:Definitely, yes.=C2=A0 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.=20 Because there is no way to stop the former but still have=C2=A0 operator overloading. =20 To reiterate, operator overloading exists in D to support the=C2=A0 inclusion of arithmetic library types. Any other purpose is=C2=A0 discouraged, and that includes expression templates and things=C2=A0 like << for iostreams.=20 This is an obsolete way of thinking about operators. Operator=C2=A0 overloading exists to make the programmer's life easier, and=C2=A0 limiting the ways in which a valuable tool can be used drives=C2=A0 people to languages which allow them to be more expressive.For my job I write Python. We use a database layer called=C2=A0 sqlalchemy that allows us to express queries by writing, for=C2=A0 example, `session.query(some_table).filter(row1 =3D=3D row2)` and I=C2=A0 cannot begin to express how useful this is when writing code,=C2=A0 when maintaining code, and when attempting to understand code=C2=A0 that someone else wrote.Definitely. I spend a lot of my time trying to inculcate people into DSL-based thinking as an extension of abstraction and leading towards understanding and modelling the solution to problems in the domain. Python has it's problems, C++ more, but this is a far superior way of going than the Java approach of "operator overloading is too hard for programmers to deal with so let's ban it". Hence Groovy, Scala, Kotlin, Ceylon, etc. all of which bring back this feature Java eschewed from C++ =E2=80=93 possibly because the Oak developers had their problems.=C2=A0The objective should never be to stop the programmer from doing=C2=A0 something because you personally dislike the practice.I guess it depends on whether the language is wanting to gain traction in the market or remain a pet project. --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Sep 29 2016
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.
Sep 29 2016
On Thu, 2016-09-29 at 11:50 +0000, Minty Fresh via Digitalmars-d wrote:On Thursday, 29 September 2016 at 11:29:55 UTC, Russel Winder=C2=A0 wrote:But, but, but, << means very much less than, everyone knows this. What is this bitshifting of which you speak. !=20 However, this has come up many times, and every time Walter=C2=A0 says "no, it's wrong". Whilst the C++ iostreams << may have=C2=A0 problems, using this as a single point argument as to why=C2=A0 overloading fails in all other cases except numeric arithmetic=C2=A0 is bad philosophy. In my view this is holding D back.=20 To add some thoughts to this, =20 The use of << being bad is purely a matter of opinion. If you believe that << is to only be used for bit-shifting=C2=A0 operations, you might hold the view that it is bad.On the other hand, if you come from a background like Haskell or=C2=A0 Ruby, you might have a very different opinion.Is there anyone from an Haskell background here. :-) Anyway everyone who wants to make Haskell code mainstream is using Frege.ie. In Ruby, << is named the shovel operator. It's uses are things=C2=A0 like appending an element into an Array.Groovy, and indeed Python, likewise. We ignore the mess Algol68 and Scala have got themselves into with this.=20 Hence, a less opinionated point is necessary here.Opinionated is not always bad. Look at Go, the developers know that there is no sane way of doing generics so they ban it. Also they know that exceptions are totally incomprehensible to all programmers so they ban them. Rust developers know that all memory handling must be explicit all the world falls apart. Opinionated languages clearly get traction =E2=80=93 not usually because of the opinions, it has to be said, = more usually because of the amount of money thrown at marketing. Except Python, obviously. --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Sep 29 2016
On Thursday, 29 September 2016 at 12:20:42 UTC, Russel Winder wrote:Opinionated is not always bad. Look at Go, the developers know that there is no sane way of doing generics so they ban it. Also they know that exceptions are totally incomprehensible to all programmers so they ban them. Rust developers know that all memory handling must be explicit all the world falls apart. Opinionated languages clearly get traction – not usually because of the opinions, it has to be said, more usually because of the amount of money thrown at marketing. Except Python, obviously.Reminds me of this - https://twitter.com/paniq/status/757951588057096192
Sep 29 2016
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.
Sep 28 2016
On 28.09.2016 22:16, Walter Bright wrote:On 9/28/2016 6:58 AM, Timon Gehr wrote:This is not surprising. C++ has no good options.Yet this "obviously bad" idea regularly resurfaces as a cool use of expression templates and respected people in the industry like it and advocate it. ...An excellent example of that is the std.regex package.It's actually a bad example, because it is irrelevant: it is obviously a bad idea to implement regex using operator overloading, because the regex operators have no D equivalent.What's wrong with that usage? (This is NOT expression templates.)Assume I have two symbolic expressions a and b: Expression a=variable("a"), b=variable("b"); Why should I be allowed to do auto c = a + b; // symbolic value a + b but not auto d = a <= b; // symbolic value a <= bBecause there is no way to stop the former but still have operator overloading. ...No. It's symbolic computation at run time. Think Wolfram Mathematica.The string parsing approach is not useful here: how do I use existing expressions that are accessible in the scope to build new expressions?You seem to be asking for expression templates.
Sep 28 2016
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).
Sep 28 2016
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.(This is NOT expression templates.)Right, but it's an enabler of expression templates. Discussion of more powerful operator overloading cannot be divorced from expression templates, and once ETs are in we'll be stuck with them forever. 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. In that category are things like text macros, AST macros, user-defined syntax, non-arithmetic operator overloading, and expression templates.
Sep 28 2016
On Thursday, 29 September 2016 at 04:15:32 UTC, Walter Bright wrote:On 9/28/2016 1:40 PM, Timon Gehr wrote: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.)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.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.
Sep 28 2016
On Thursday, 29 September 2016 at 04:39:37 UTC, Minty Fresh wrote:This applies to operator overloads just like everything else. They're just syntactic sugar for functions. Documenting their behavior is just as necessary.I disagree with this. Operators are different in that the symbols themselves already have meaning and are a core part of the language. When I see a function in code that was written by someone else, I have no idea what it really does, no matter how it was named, until I pull up the documentation or the source and actually read it. I expect that I'm going to have to do that. Using operators in ways they were not intended to be used is breaking my expectations. When I'm scanning D code and see a '+', I'm going to think addition (and not concatenation or appending or anything else). It isn't going to occur to me that the types involved are doing something completely different and I ought to look in the documentation to see what that is. And I shouldn't have to worry about it. That sort of cognitive disruption is really annoying. In D1, operators were overloaded *by name* and not by symbol. I loved that, because it made it quite clear that opAdd is an addition and doing something different with it would be akin to having a function named printFoo launching an audio player. And if printFoo *did* launch an audio player, I'm quite confident most programmers would consider the function horribly misnamed. The same applies to operators, as I see it.
Sep 28 2016
On Wednesday, September 28, 2016 21:15:32 Walter Bright via Digitalmars-d wrote:Because then something other than comparison is happening with <=, <, >, >= and there'll be nothing in the code to give the user a hint.[snip]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.A related issue is generic code. Having the same operator or function name mean essentially the same thing for every type that has it is required for generic code to work. To some extent, that's also checked by having the semantics of the code checked (e.g. that front returns something as opposed to being void or that popFront takes no arguments), but there's only so much that can be done there. And no, even then, you can't guarantee that the function in question operates the way that the generic code expects. But if common function names mean the same thing and act the same way for types in general, then they play well with generic code, whereas as soon as someone takes a common function and makes it do something different from what's normal, it does not play well with generic code at all. Overloaded operators are the prime example of this, because there is a clear expectation for what their basic behaviors are, and they're functions that are built into the language. Next in line would be extremely common idioms such as the range-based functions. Once you start getting to less common stuff, then the issue of whether a function with a particular name acts the same way in one library as another is significantly diminished, but for the common stuff, it's critical for generic code that folks don't go and make common functions operate in a way that is inconsistent with how they would function on most every other type out there and how everyone is going to expect them to behave when they see them. Having a type implement something like expression templates is an utter disaster for generic code, just like it's a disaster if front does something like call popFront every time that it's called. Consistent semantics for common functions is very important for generic code as well as for code legibility and maintainability. - Jonathan M Davis
Sep 28 2016
On 29.09.2016 06:15, Walter Bright wrote:On 9/28/2016 1:40 PM, Timon Gehr wrote:You also complained about '+'.What's wrong with that usage?Because then something other than comparison is happening with <=,<, >,Actually, comparison is precisely what is happening. The hint about what is happening precisely is that the entire codebase does symbolic computations all over the place, and it is very clear what the involved types are.= and there'll be nothing in the code to give the user a hint....They work today, just not with comparison operators.(This is NOT expression templates.)Right, but it's an enabler of expression templates. Discussion of more powerful operator overloading cannot be divorced from expression templates, and once ETs are in we'll be stuck with them forever. ...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. ...That is and has always been the responsibility of the programmer. (IDEs don't even help that much.)In that category are things like text macros, AST macros, user-defined syntax, non-arithmetic operator overloading, and expression templates.What's the definition of "arithmetic" here?
Sep 29 2016
On Thu, 29 Sep 2016 10:41:38 +0200, Timon Gehr wrote:On 29.09.2016 06:15, Walter Bright wrote:To take it the other way, D could enforce that the return type of arithmetic operators is compatible with at least one of the operands -- by implicit cast or constructor or being the same type. Wouldn't that be fun?On 9/28/2016 1:40 PM, Timon Gehr wrote:They work today, just not with comparison operators.(This is NOT expression templates.)Right, but it's an enabler of expression templates. Discussion of more powerful operator overloading cannot be divorced from expression templates, and once ETs are in we'll be stuck with them forever. ...
Sep 29 2016
On 30.09.2016 03:15, Chris Wright wrote:On Thu, 29 Sep 2016 10:41:38 +0200, Timon Gehr wrote:It wouldn't infer with any of my use cases, but I don't see the point.On 29.09.2016 06:15, Walter Bright wrote:To take it the other way, D could enforce that the return type of arithmetic operators is compatible with at least one of the operands -- by implicit cast or constructor or being the same type.On 9/28/2016 1:40 PM, Timon Gehr wrote:They work today, just not with comparison operators.(This is NOT expression templates.)Right, but it's an enabler of expression templates. Discussion of more powerful operator overloading cannot be divorced from expression templates, and once ETs are in we'll be stuck with them forever. ...Wouldn't that be fun?Certainly.
Sep 30 2016
On 30.09.2016 21:02, Timon Gehr wrote:On 30.09.2016 03:15, Chris Wright wrote:On a related note: alias Seq(T...)=T; struct S{ int x; S opBinary(string op:"+",T...)(T args){ S r=this; foreach(a;args) r.x+=a; return r; } } void main(){ import std.stdio; assert(S(1) + Seq!(2,3,4) == S(10)); }...Wouldn't that be fun?Certainly.
Sep 30 2016
On 09/30/2016 03:18 PM, Timon Gehr wrote:On 30.09.2016 21:02, Timon Gehr wrote:That looks awfully cool! -- AndreiOn 30.09.2016 03:15, Chris Wright wrote:On a related note: alias Seq(T...)=T; struct S{ int x; S opBinary(string op:"+",T...)(T args){ S r=this; foreach(a;args) r.x+=a; return r; } } void main(){ import std.stdio; assert(S(1) + Seq!(2,3,4) == S(10)); }...Wouldn't that be fun?Certainly.
Sep 30 2016
On 30.09.2016 22:14, Andrei Alexandrescu wrote:On 09/30/2016 03:18 PM, Timon Gehr wrote:[my code here]On 30.09.2016 21:02, Timon Gehr wrote:That looks awfully cool! -- AndreiOn 30.09.2016 03:15, Chris Wright wrote:On a related note: alias Seq(T...)=T; struct S{ int x; S opBinary(string op:"+",T...)(T args){ S r=this; foreach(a;args) r.x+=a; return r; } } void main(){ import std.stdio; assert(S(1) + Seq!(2,3,4) == S(10)); }...Wouldn't that be fun?Certainly.
Sep 30 2016
On Wed, 2016-09-28 at 21:15 -0700, Walter Bright via Digitalmars-d wrote:On 9/28/2016 1:40 PM, Timon Gehr wrote:This is a very "tunnel vision" view of programming language and the way programs are constructed and perceived. But sadly I know we have been round this many times, and you will not be changing you viewpoint. But even though I know nothing will change, I feel required to take on the challenge again. Until you cite psychology of programming experimental data to back up any position, it is all just opinion and personal experience. I am happy with << as very much less than, or output depending on context, you are not. But it is bad philosophy for me to say << is comprehensible to me and so it is comprehensible to everyone, and equally bad philosophy for you to say the same with s/comprehensible/incomprehensible/. This sort of thing happened in Python with the reduce function, leaving Python 3 in a truly inconsistent position regarding higher order functions. So when it comes to writing DSLs I'll stick with Python and Groovy, until D gets it right. [=E2=80=A6] --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder=20 What's wrong with that usage?=20 Because then something other than comparison is happening with <=3D, <,, >=3D and=C2=A0there'll be nothing in the code to give the user a hint.
Sep 29 2016
On Wednesday, 28 September 2016 at 20:16:08 UTC, Walter Bright wrote:On 9/28/2016 6:58 AM, Timon Gehr wrote:The fact that it's not possible to overload < but have to use the ternary opCmp is even a performance problem. All std algorithms only use less as a predicate, leading to lots of unnecessary cycles when e.g. sorting UDTs. While I agree with your point on expression templates, overloading comparison operators has valid use cases.Yet this "obviously bad" idea regularly resurfaces as a cool use of expression templates and respected people in the industry like it and advocate it.An excellent example of that is the std.regex package.It's actually a bad example, because it is irrelevant: it is obviously a bad idea to implement regex using operator overloading, because the regex operators have no D equivalent.Assume I have two symbolic expressions a and b: Expression a=variable("a"), b=variable("b"); Why should I be allowed to do auto c = a + b; // symbolic value a + b but not auto d = a <= b; // symbolic value a <= bBecause there is no way to stop the former but still have operator overloading.
Oct 01 2016
On 10/1/16 3:13 AM, Martin Nowak wrote:The fact that it's not possible to overload < but have to use the ternary opCmp is even a performance problem. All std algorithms only use less as a predicate, leading to lots of unnecessary cycles when e.g. sorting UDTs.I've also been often annoyed by having to write return a < b ? -1 : a > b; in e.g. checkedint. Does inlining take care of this? -- Andrei
Oct 01 2016
On 10/1/16 7:33 AM, Andrei Alexandrescu wrote:On 10/1/16 3:13 AM, Martin Nowak wrote:Apparently in dmd the generated code is less efficient: https://goo.gl/OWxbA0. In gdc it's the same: https://godbolt.org/g/NmUyXM. I couldn't test with ldc, http://ldc.acomirei.ru seems down. -- AndreiThe fact that it's not possible to overload < but have to use the ternary opCmp is even a performance problem. All std algorithms only use less as a predicate, leading to lots of unnecessary cycles when e.g. sorting UDTs.I've also been often annoyed by having to write return a < b ? -1 : a > b; in e.g. checkedint. Does inlining take care of this? -- Andrei
Oct 01 2016
On Saturday, 1 October 2016 at 07:13:39 UTC, Martin Nowak wrote:The fact that it's not possible to overload < but have to use the ternary opCmp is even a performance problem. All std algorithms only use less as a predicate, leading to lots of unnecessary cycles when e.g. sorting UDTs.On Saturday, 1 October 2016 at 11:53:07 UTC, Andrei Alexandrescu wrote:Apparently in dmd the generated code is less efficient: https://goo.gl/OWxbA0. In gdc it's the same: https://godbolt.org/g/NmUyXM. I couldn't test with ldc, http://ldc.acomirei.ru seems down. -- AndreiOn Saturday, 1 October 2016 at 06:46:31 UTC, Russel Winder wrote:This debate is about whether D constrains people as Java does or whether it enables people as C++ and Python do. Or use C++ or Python which allow for this. Fine, end of D having a future amongst a large section of the programming population. This is fine. Unless D wants to be a player in this game. This has already been done, read the thread. SQLAlchemy. The expression language is a a lovely builder DSL for constructing SQL entirely in Python with no parser overhead. No operator overloading, no DSL for builder languages. See same on the JVM: in Java you can't do it, Kotlin, Ceylon, Scala, Groovy, do it beautifully, and a lot of people do.This isn't a PR yet because it's not nearly ready for general consumption, but these are all good points and I'd greatly appreciate if you would all please take a few minutes to express them in the DIP and get the changes merged so that we can have something that lays out clearly the pros and cons of this change. https://github.com/pineapplemachine/DIPs/blob/operator_overload_expansion/DIPs/DIP1003.md
Oct 01 2016
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.
Sep 28 2016
On 2016-09-28 06:02, Walter Bright wrote:The limitations are deliberate based on the idea that comparison operators need to be consistent and predictable, and should have a close relationship to the mathematical meaning of the operators. Overloading <= to mean something other than "less than or equal" is considered poor style in D, and the same goes for the other arithmetic operators.If that is not allowed, why is this allowed: struct MyInt { int value; MyInt opBinary(string op)(MyInt rhs) if (op == "+") { return MyInt(value - rhs.value); } } assert(MyInt(3) + MyInt(3) == MyInt(0)); The language you just provide a set of tools, then it's up the to the programmer to do what he/she wants to do.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.That's one of the ugliest things about D. Because suddenly you will not have any help of any tools, like editors, IDEs, linters, syntax analysis and so on. One also needs to implement a complete parser, how many complete parsers do we have for D? -- /Jacob Carlborg
Sep 28 2016
On 9/28/2016 11:48 PM, Jacob Carlborg wrote:If that is not allowed, why is this allowed:I.e. you can overload '+' to do bad things. Yes, you can, and as I replied upthread that can be done because there's no way to prevent that while having operator overloading at all. But that is not justification for allowing such disasters for the comparison operators. I.e. one weakness is not justification for opening the door to all weakness. Interestingly, by shutting the door on misuse of the comparison operators, it seems D has been successful in discouraging nutburger designs like overloading '+' to mean 'OR'.The language you just provide a set of tools, then it's up the to the programmer to do what he/she wants to do.That can be used to justify any feature at all.I know you really want AST macros for D. We've discussed that at length before. BTW, there's a CTFE parser generator for D around somewhere.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.That's one of the ugliest things about D. Because suddenly you will not have any help of any tools, like editors, IDEs, linters, syntax analysis and so on. One also needs to implement a complete parser, how many complete parsers do we have for D?
Sep 29 2016
On Thursday, 29 September 2016 at 07:58:26 UTC, Walter Bright wrote:On 9/28/2016 11:48 PM, Jacob Carlborg wrote:This is not an argument to justify adding just any feature, it's an argument that it is idiocy to give a programmer a powerful tool, and then impose arbitrary limitations upon how they are allowed to use it. One of the most popular topics of discussion in this forum is "Why is D not more widely adopted?" and "What can we do to get broader adoption for D?" Perhaps one of the more obvious answers is: Do not prevent programmers from doing something solely on the basis that _you_ would not want to do it. I think camelCase is hideous, but does that mean I should forbid another programmer defining symbols in that style? Of course not. That they are able to write their code that way doesn't mean I have to, and doesn't mean I have to use or interface with their code. I agree that '+' should always mean addition and '~' should always mean concatenation, but does that mean I should forbid another programmer from defining them differently? Of course not. Just because they are able to do it that way doesn't mean I have to, or that I have to use their code. If I thought '>' and '<' should always mean arithmetic comparison, does that mean I should forbid another programmer from defining them differently? You need to understand that _you are not the only one writing code in this language_. Your use cases do not summarize all possible use cases. That you do not need to use a tool in a specific way is not a valid argument against allowing others to use the tool that way. Give us a rational argument. We are unconcerned with your personal dogma. What you refer to as a weakness I view as a strength. Programmers require more flexibility and expressiveness, not less.If that is not allowed, why is this allowed:I.e. you can overload '+' to do bad things. Yes, you can, and as I replied upthread that can be done because there's no way to prevent that while having operator overloading at all. But that is not justification for allowing such disasters for the comparison operators. I.e. one weakness is not justification for opening the door to all weakness. Interestingly, by shutting the door on misuse of the comparison operators, it seems D has been successful in discouraging nutburger designs like overloading '+' to mean 'OR'.The language you just provide a set of tools, then it's up the to the programmer to do what he/she wants to do.That can be used to justify any feature at all.
Sep 29 2016
On 2016-09-29 11:31, pineapple wrote:This is not an argument to justify adding just any feature, it's an argument that it is idiocy to give a programmer a powerful tool, and then impose arbitrary limitations upon how they are allowed to use it. One of the most popular topics of discussion in this forum is "Why is D not more widely adopted?" and "What can we do to get broader adoption for D?" Perhaps one of the more obvious answers is: Do not prevent programmers from doing something solely on the basis that _you_ would not want to do it. I think camelCase is hideous, but does that mean I should forbid another programmer defining symbols in that style? Of course not. That they are able to write their code that way doesn't mean I have to, and doesn't mean I have to use or interface with their code. I agree that '+' should always mean addition and '~' should always mean concatenation, but does that mean I should forbid another programmer from defining them differently? Of course not. Just because they are able to do it that way doesn't mean I have to, or that I have to use their code. If I thought '>' and '<' should always mean arithmetic comparison, does that mean I should forbid another programmer from defining them differently? You need to understand that _you are not the only one writing code in this language_. Your use cases do not summarize all possible use cases. That you do not need to use a tool in a specific way is not a valid argument against allowing others to use the tool that way. Give us a rational argument. We are unconcerned with your personal dogma. What you refer to as a weakness I view as a strength. Programmers require more flexibility and expressiveness, not less.Well said. -- /Jacob Carlborg
Sep 29 2016
On 2016-09-29 09:58, Walter Bright wrote:I.e. you can overload '+' to do bad things. Yes, you can, and as I replied upthread that can be done because there's no way to prevent that while having operator overloading at all. But that is not justification for allowing such disasters for the comparison operators. I.e. one weakness is not justification for opening the door to all weakness.You're using the same justification when rejecting most feature requests you don't like: you had one bad experience with C++ and therefore it must be banned for all eternity. It's not a valid argument.Interestingly, by shutting the door on misuse of the comparison operators, it seems D has been successful in discouraging nutburger designs like overloading '+' to mean 'OR'.It's also shutting the door on doing a lot of useful things. My goal is no to use the comparison operators to mean something different than comparison. The goal is, for example, to build a corresponding SQL query out of an expression. But the == operator would still be used for equality. One major issue with using string literals is, if we use the SQL query as an example again, as follows: First try: auto bar = `"bar"`; auto query = "SELECT * FROM foo WHERE bar = " ~ bar; Is have the issue of SQL injection. Second try: auto bar = "bar"; auto foo = "foo"; auto q = query("SELECT * FROM foo WHERE bar = $1 AND foo = $2", bar, foo); This has the issue that the value and the place of where a value is used far away from each other in the code making it more difficult to read. This was "solved" in Rails by using an associative array mapping the column names to the values: foo = "foo" bar = "bar" Foo.where(bar: bar, foo: foo) That has the issue of only working with equality and "AND". Now way to do less than or "OR". Third try: auto foo = "foo"; auto bar = "bar"; Foo.where(q => q.foo == foo && q.bar == "bar"); The above expression would be translated to the query in the second example, with the values properly escaped. Now this is how I want the code to look like.The language you just provide a set of tools, then it's up the to the programmer to do what he/she wants to do.That can be used to justify any feature at all.I know you really want AST macros for D. We've discussed that at length before. 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. -- /Jacob Carlborg
Sep 29 2016
On Thursday, 29 September 2016 at 12:54:54 UTC, Jacob Carlborg wrote: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.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.
Sep 29 2016
I.e. you can overload '+' to do bad things. Yes, you can, and as I replied upthread that can be done because there's no way to prevent that while having operator overloading at all. But that is not justification for allowing such disasters for the comparison operators. I.e. one weakness is not justification for opening the door to all weakness.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? Wouldn't the current rules discourage someone from implementing CAS like library in D?
Sep 29 2016
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)
Sep 29 2016
On Thu, 2016-09-29 at 10:52 -0700, Walter Bright via Digitalmars-d wrote:On 9/29/2016 9:41 AM, Sai wrote:How wonderfully Java. --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder=20 If I understand the issue correctly, one will not be able to overload <=3D, >, etc for symbolic math, like CAS (mimicking mathematica for example), how can I do it now?=20 =20 =C2=A0=C2=A0=C2=A0=C2=A0a.isLessThan(b)
Sep 29 2016
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: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.On 9/29/2016 9:41 AM, Sai wrote:How wonderfully Java.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)
Sep 29 2016
On Thursday, September 29, 2016 18:14:22 Minty Fresh via Digitalmars-d wrote:On Thursday, 29 September 2016 at 18:07:37 UTC, Russel Winder wrote:Then you could always do something like a.myOp!"<"(b) and a.myOp!">="(b) if you still want to have the operator in there somewhere. You can name the functions whatever you want. You just can't use overloaded operators for it, since it would not be in line with what the operators are supposed to mean and be used for. - Jonathan M DavisOn Thu, 2016-09-29 at 10:52 -0700, Walter Bright via Digitalmars-d wrote: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.On 9/29/2016 9:41 AM, Sai wrote:How wonderfully Java.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)
Sep 29 2016
On Thursday, 29 September 2016 at 18:38:42 UTC, Jonathan M Davis wrote:Then you could always do something like a.myOp!"<"(b) and a.myOp!">="(b) if you still want to have the operator in there somewhere. You can name the functions whatever you want. You just can't use overloaded operators for it, since it would not be in line with what the operators are supposed to mean and be used for. - Jonathan M DavisAlso with mixins and a CTFE D parser you could replace the operators by any desired function calls.
Sep 29 2016
On Thursday, 29 September 2016 at 18:38:42 UTC, Jonathan M Davis wrote:You just can't use overloaded operators for it, since it would not be in line with what the operators are supposed to mean and be used for.This is not a valid argument because what an operator is "supposed to mean" is up to the programmer who wishes to implement that operator for their data type. Not up to me. Not up to you. Your thinking like this limits D's viability for real-world code. Programmers do not care how you think they are supposed to use the language. They care only that they can get their job done in a way that makes sense to them. What makes sense to them will not be the same as what makes sense to you. Relinquish the notion that you or anyone can have the slightest idea what any language feature is "supposed to mean and be used for".
Sep 29 2016
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.
Sep 29 2016
On Thursday, September 29, 2016 19:11:55 pineapple via Digitalmars-d wrote:On Thursday, 29 September 2016 at 18:38:42 UTC, Jonathan M Davis wrote:Every language feature is designed with a purpose. Sometimes that purpose is broader than other times. And once the feature is there, you can do whatever is legal to do with the feature whether that was really what it was intended for or not, but if what you're trying to do goes against what the feature was designed for, don't expect to get support for making it do more stuff that goes against why it's in the language in the first place - especially when plenty of folks think that what you're trying to do is bad practice. The reality of the matter is that D's operator overloading was designed specifically so that you could overload the built-in operators to be used with your own types so that they could act like the built-in types. It was not intended or designed to allow for the symbols use for those operators to then be used for other arbitrary stuff that's unrelated to what they mean for the built-in types. The decisions made in how the operators are overloaded were geared entirely towards better supporting having your types act like built-in types, and none of it was designed with the idea that you would do arbitrary stuff via overloading the operators (which is why the language does stuff like derive some operators from others; it supports the goal of making them work like the built-in types, and supporting arbitrary usage of those operators was never a goal, so losing out on the ability is not considered to be a problem). 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. And there are plenty of folks who think that overloading operators to do stuff fundamentally different from how they work for the built-in types is bad practice and consider it to be an abuse of operator overloading. So, the fact that D limits that is going to be viewed as positive by many folks. You're obviously free to do whatever you want with overloaded operators in D within the bounds of how they work, but we're not going to change them with the goal of making them less restrictive about mimicking the operators for the built-in types when the entire reason that they're in the language is to mimic the operators for the built-in types. And if you do try and make them work differently than for the built-in types, then your code is likely to be considered by many to be following bad programming practices. - Jonathan M DavisYou just can't use overloaded operators for it, since it would not be in line with what the operators are supposed to mean and be used for.This is not a valid argument because what an operator is "supposed to mean" is up to the programmer who wishes to implement that operator for their data type. Not up to me. Not up to you. Your thinking like this limits D's viability for real-world code. Programmers do not care how you think they are supposed to use the language. They care only that they can get their job done in a way that makes sense to them. What makes sense to them will not be the same as what makes sense to you. Relinquish the notion that you or anyone can have the slightest idea what any language feature is "supposed to mean and be used for".
Sep 29 2016
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`.
Sep 29 2016
On Thursday, 29 September 2016 at 19:39:35 UTC, Jonathan M Davis wrote:The reality of the matter is that D's operator overloading was designed specifically so that you could overload the built-in operators to be used with your own types so that they could act like the built-in types. It was not intended or designed to allow for the symbols use for those operators to then be used for other arbitrary stuff that's unrelated to what they mean for the built-in types.I repeat: Your thinking like this limits D's viability for real-world code. Yes, I understand, the reason operator overloading works the way it does now is because members of the community wanted to arbitrarily limit programmers working in the language. Because they believed theirs was the singular appropriate way to use the language, to the exclusion of all others. I'm opinionated too, but I also have the presence of mind to recognize that my opinions are not universal, and they are certainly no basis for imposing arbitrary limits upon another person's behavior. On Thursday, 29 September 2016 at 19:39:35 UTC, Jonathan M Davis wrote:And there are plenty of folks who think that overloading operators to do stuff fundamentally different from how they work for the built-in types is bad practice and consider it to be an abuse of operator overloading. So, the fact that D limits that is going to be viewed as positive by many folks.Let me see if I understand your thinking: What you're saying is that because some people may not want to use a feature in a specific way, D should disallow anyone from using the feature in that way? That, somehow, contrary to logic, you believe this contributes positively to D's usability and appeal?
Sep 29 2016
On Thursday, September 29, 2016 20:16:00 pineapple via Digitalmars-d wrote:On Thursday, 29 September 2016 at 19:39:35 UTC, Jonathan M Davis wrote:Except that the limits aren't arbitrary. Walter designed D's overloaded operators for a specific purpose - to mimic the built-in operators. If you want to make them do something else, and you're able to do so with how they're designed, then that's your choice, but that's not what they're designed for, and there is no attempt to support it. You could just as easily ask why D's overloaded operators don't support your code and complain that the current limitation on that is arbitary. The feature _could_ have been made to do something like that, but that wasn't its intended purpose, and there are reasons why it's a bad idea, so that's not how D's operator overloading was designed. The comparison operators have a specific purpose, and the functions for overloading them were designed with that in mind. It just so happens that that conflicts with what you want to do, but that doesn't mean that the limitation is arbitrary. Rather, code correctness and conciseness of code was valued, so they were overloaded using functions that could be used to derive those operators rather than explicitly overloading each operator individually. And because the ability to overload operators to do aribtrary stuff was never one of the goals of the design, the fact that having functions like opEquals and opCmp conflicted with the ability to overload each comparison operator to do arbitrary stuff was not considered to be a problem. It's a design tradeoff that just doesn't happen to be in line with what you want to do. Just because C++ overloaded operators in a way that happens to support doing arbitrary stuff with all of them doesn't mean that D needs to or that the restriction is arbitrary.The reality of the matter is that D's operator overloading was designed specifically so that you could overload the built-in operators to be used with your own types so that they could act like the built-in types. It was not intended or designed to allow for the symbols use for those operators to then be used for other arbitrary stuff that's unrelated to what they mean for the built-in types.I repeat: Your thinking like this limits D's viability for real-world code. Yes, I understand, the reason operator overloading works the way it does now is because members of the community wanted to arbitrarily limit programmers working in the language. Because they believed theirs was the singular appropriate way to use the language, to the exclusion of all others. I'm opinionated too, but I also have the presence of mind to recognize that my opinions are not universal, and they are certainly no basis for imposing arbitrary limits upon another person's behavior.On Thursday, 29 September 2016 at 19:39:35 UTC, Jonathan M Davis wrote:There are plenty of folks who think that overloading operators to mean anything other than what they mean for the built-in types is bad practice. Walter seems to be in agreement with that. So, when he designed D's operator overloading, he did not attempt to support that. He didn't do a lot to prevent it either, but in cases where it made sense to derive multiple operators from a single function, he did so, even if it meant that you then couldn't overload those operators to mean something other than what they meant for the built-in types, because he considered what you got out of combining them was worth far more than trying to support what many think is bad practice. t's not like Walter sat down and tried to prevent every misuse of operator overloading. He simply didn't choose a design that fully supports such misuse. Rather, he chose a design that better supports the intended use. The tradeoff just so happens to leave you without being able to do something that he considers to be bad practice, so he doesn't see it as a loss. And neither do I. But that wasn't even the primary goal of why the operators work they do. It's just a side effect of there being design goals that were better served by a design that happened to inhibit operator overloading abuse. You'd have a much better argument if the language specifically did stuff to hobble the abuse of overloaded operators. It doesn't. It just doesn't implement operator overloading in a way that fully supports it. And Walter is clearly not in favor of implementing such a language "enhancement," because he thinks that it would just enable bad code, so I think that it's clear that it's not going to happen. - Jonathan M DavisAnd there are plenty of folks who think that overloading operators to do stuff fundamentally different from how they work for the built-in types is bad practice and consider it to be an abuse of operator overloading. So, the fact that D limits that is going to be viewed as positive by many folks.Let me see if I understand your thinking: What you're saying is that because some people may not want to use a feature in a specific way, D should disallow anyone from using the feature in that way? That, somehow, contrary to logic, you believe this contributes positively to D's usability and appeal?
Sep 29 2016
On Thursday, 29 September 2016 at 20:16:00 UTC, pineapple wrote:I repeat: Your thinking like this limits D's viability for real-world code.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.
Sep 29 2016
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.
Sep 29 2016
On Thursday, 29 September 2016 at 22:37:51 UTC, Minty Fresh wrote:On Thursday, 29 September 2016 at 22:27:50 UTC, bachmeier wrote:I seeYou'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.
Sep 29 2016
On Thursday, September 29, 2016 22:37:51 Minty Fresh via Digitalmars-d wrote:On Thursday, 29 September 2016 at 22:27:50 UTC, bachmeier 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 DavisYou'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.
Sep 29 2016
On Thu, 29 Sep 2016 17:50:54 -0700, Jonathan M Davis via Digitalmars-d 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 a line of code buried somewhere that changes the meaning of the rest of the code. Operator overloading is restricted to a specific user-defined type. With such a dramatic difference in the scope of the change, the analogy is useless.
Sep 29 2016
On Friday, 30 September 2016 at 01:07:49 UTC, Chris Wright wrote:The perl example is a line of code buried somewhere that changes the meaning of the rest of the code. Operator overloading is restricted to a specific user-defined type. With such a dramatic difference in the scope of the change, the analogy is useless.I was responding to someone that wrote: "I also have the presence of mind to recognize that my opinions are not universal, and they are certainly no basis for imposing arbitrary limits upon another person's behavior". I gave an example of what happens when you don't want "arbitrary limits". 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 have fun debating design decisions that were made long ago and aren't going to change.
Sep 30 2016
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.
Sep 30 2016
On 9/30/2016 1:14 PM, Minty Fresh wrote:MetathesiophobiaRepeatedly suggesting people who don't agree with you have mental disorders does not advance your case and is not appreciated here. 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.
Sep 30 2016
On Friday, 30 September 2016 at 22:38:07 UTC, Walter Bright wrote: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.A good idea. I have written a rough initial draft for this DIP and it currently resides here, in a fork: https://github.com/pineapplemachine/DIPs/blob/operator_overload_expansion/DIPs/DIP1003.md I invite anyone with an opinion - which I imagine is just about everyone who has participated in this thread - to please contribute to the DIP before it's submitted as a PR and for review. I ask that arguments for and against listed in the DIP not include anything to the effect of merely "it would offer more flexibility" or "it would offer too much flexibility", as I think several pages of discussion have made clear that those holding either opinion are not likely to be swayed by arguments taking the opposing form.
Sep 30 2016
On Fri, 2016-09-30 at 15:38 -0700, Walter Bright via Digitalmars-d wrote:A more productive way forward is for you (and those who agree with you) to=C2=A0 prepare a formal DIP and submit it. It's the way significant language change=C2=A0 proposals are done.But is the effort worth it? Will the DIP and PR be assessed? Does it have any chance of success? Is there any chance of this long standing position of D on overloading operators being overturned? Saying "Go prepare a DIP" is both indicating the right thing to do, but also a mechanism of deflecting the idea from having any chance of success at all. So does a well prepared DIP have a chance of changing D's operator overloading or not? =C2=A0 --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Sep 30 2016
On Friday, 30 September 2016 at 22:38:07 UTC, Walter Bright wrote:On 9/30/2016 1:14 PM, Minty Fresh wrote: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.MetathesiophobiaRepeatedly suggesting people who don't agree with you have mental disorders does not advance your case and is not appreciated here.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.
Oct 01 2016
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.Which language is more widely used? D or Perl? Let me see if I understand your argument: We can't make D more expressive because a language far more popular than D is so expressive it makes it possible to do unconventional things, if you are so inclined?
Sep 30 2016
On Friday, September 30, 2016 09:55:36 pineapple via Digitalmars-d wrote:On Friday, 30 September 2016 at 00:50:54 UTC, Jonathan M Davis wrote:perl is always widely considered to be a horrible language even if it is useful. And the example that was given for what you can do with perl is pretty insane. Regardless, D already has a lot of powerful stuff in it, much of which will allow you to blow your foot off if you're really inclined to. The overloaded operators just so happened to be implemented in a way that doesn't let you blow your feet off as freely as C++'s overloaded operators will let you do. - Jonathan M DavisExcept 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.Which language is more widely used? D or Perl? Let me see if I understand your argument: We can't make D more expressive because a language far more popular than D is so expressive it makes it possible to do unconventional things, if you are so inclined?
Sep 30 2016
On 30.09.2016 18:11, Jonathan M Davis via Digitalmars-d wrote:Regardless, D already has a lot of powerful stuff in it, much of which will allow you to blow your foot off if you're really inclined to. The overloaded operators just so happened to be implemented in a way that doesn't let you blow your feet off as freely as C++'s overloaded operators will let you do.OTOH, feet are useless if you are not allowed to walk (even if you choose not to blow them off).
Sep 30 2016
On Friday, 30 September 2016 at 09:55:36 UTC, pineapple wrote:On Friday, 30 September 2016 at 00:50:54 UTC, Jonathan M Davis wrote:But operator overloading doesn't increase the language expressiveness. They provide nothing that you can't already do using ordinary function calls. So forget expressiveness as an argument. Operator overload is syntactic sugar, added to serve a single purpose: to allow mimic buildin types. So they should provide everything needed to do so, and nothing more. Adding more may be asked for, but this is not reasonable, because it is unrelated to the original purpose but increases only the possibilities to obfuscate the code by doing something misleading (there are already endless such possibilities, but that makes asking for more no more reasonable). On Friday, 30 September 2016 at 19:09:25 UTC, Timon Gehr 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.Let me see if I understand your argument: We can't make D more expressive because a language far more popular than D is so expressive it makes it possible to do unconventional things, if you are so inclined?On 30.09.2016 18:11, Jonathan M Davis via Digitalmars-d wrote:You are allowed to walk. You can express everything that is possible with operator overloading in lots of other ways. And you can express everything that operator overloading was designed for with it - but maybe not everything beyond that. Use other ways to express such. If the compactness of expression written using operators is everything you are interested in - define some language and write a parser for it, and enjoy how short you can express everything you need with it. You can even write such stuff directly in your D code and let some string mixins massage it to compile. I can't see the point to relax the rules for operator overloading unless you can show that they prevent parts of the original design goal. PS: opCmp can return float, so the comparison can result in NaN (not conparable) - and as this is necessary to mimic some basic types (all floatingpoint types) removing this possibility would indeed prevent parts of the original design goal!Regardless, D already has a lot of powerful stuff in it, much of which will allow you to blow your foot off if you're really inclined to. The overloaded operators just so happened to be implemented in a way that doesn't let you blow your feet off as freely as C++'s overloaded operators will let you do.OTOH, feet are useless if you are not allowed to walk (even if you choose not to blow them off).
Sep 30 2016
On 30.09.2016 23:43, Dominikus Dittes Scherkl wrote:On Friday, 30 September 2016 at 09:55:36 UTC, pineapple wrote:Please don't do this; it destroys threading.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.On Friday, 30 September 2016 at 19:09:25 UTC, Timon Gehr wrote:There's a continuum here. Another data point: https://www.youtube.com/watch?v=IqhlQfXUk7w (Though here, one seems to require a good set of feet.)On 30.09.2016 18:11, Jonathan M Davis via Digitalmars-d wrote:You are allowed to walk.Regardless, D already has a lot of powerful stuff in it, much of which will allow you to blow your foot off if you're really inclined to. The overloaded operators just so happened to be implemented in a way that doesn't let you blow your feet off as freely as C++'s overloaded operators will let you do.OTOH, feet are useless if you are not allowed to walk (even if you choose not to blow them off).You can express everything that is possible with operator overloading in lots of other ways.Everybody knows this. And everyone in the above video is getting where they are going.And you can express everything that operator overloading was designed for with itHopefully. My qualm is with the design. (It is not that significant, it's basically in the "fly that sits on your face at an irregular frequency" corner.)- but maybe not everything beyond that. Use other ways to express such. If the compactness of expression written using operators is everything you are interested inAm not. You might be confusing me with someone else. But don't assume I'm going to accept huge overhead, because this does destroy the point of the original exercise at some point.- define some languageYes, I can design my own programming language. However, I don't currently have the resources to create the perfect tool for every job I face.and write a parser for it,Sure, I also have a parser. Now what? It does not integrate nicely with D code.and enjoy how short you can express everything you need with it.Conciseness never hurts. I'm interested in using notation that is similar to the one I use on paper and in scientific publications. It's also about ensuring correctness by making it easy to understand at a glance what is written down (by e.g. a domain expert). This is understood to have certain limitations (e.g. there's no built-in integral operator), but the notation that does exist corresponds precisely -- there is no misusing of names anywhere.You can even write such stuff directly in your D code and let some string mixins massage it to compile. ...This does not scale. (It works for some things, not others.)I can't see the point to relax the rules for operator overloading unless you can show that they prevent parts of the original design goal. ...Then I'm not interested in trying to convince you because you can always just claim that the use case I present was not part of the original design goal (which is not written down formally anywhere).PS: opCmp can return float, so the comparison can result in NaN (not conparable) - and as this is necessary to mimic some basic types (all floatingpoint types) removing this possibility would indeed prevent parts of the original design goal!I know. I believe I was even the first one to point this out on the NG. It was an accident, not designed. The cause was lack of some pointless restriction.
Sep 30 2016
On Fri, 2016-09-30 at 21:43 +0000, Dominikus Dittes Scherkl via Digitalmars-d wrote:But operator overloading doesn't increase the language=C2=A0 expressiveness.Expressiveness is not a metric, there isn't even a partial order, it is a qualitative thing, thus personal to a great extent. What I consider expressive and what you consider expressive likely are entirely unrelated. There can be a shared agreement or a disagreement. What is not acceptable is to state that one person's opinion is true for all people=C2=A0 =C2=A0They provide nothing that you can't already do using ordinary=C2=A0 function calls.Correct.So forget expressiveness as an argument.No.Operator overload is syntactic sugar, added to serve a single=C2=A0 purpose: to allow mimic buildin types. So they should provide=C2=A0 everything needed to do so, and nothing more. Adding more may be=C2=A0 asked for, but this is not reasonable, because it is unrelated to=C2=A0 the original purpose but increases only the possibilities to=C2=A0 obfuscate the code by doing something misleading (there are=C2=A0 already endless such possibilities, but that makes asking for=C2=A0 more no more reasonable).All high level languages are syntactic sugar, the one true language is machine code, all else is fluff. It just happens that layers of abstraction and "syntactic sugar" are really rather important to building complex software systems.=C2=A0 Any programming language is in fact a meta-language to enable people to construct new languages. All programs are DSLs for some domain. The question at hand is whether a programming language has the right tools for the job. Operator overloading is one tool in the creation of DSLs. D currently seems to have a very hobbled version of this compared to C++, Python, and a very grandiose scheme compared to Go, Fortran. This debate is about whether D constrains people as Java does or whether it enables people as C++ and Python do.You are allowed to walk. You can express everything that is=C2=A0 possible with operator overloading in lots of other ways. And you=C2=A0 can express everything that operator overloading was designed for=C2=A0 with it - but maybe not everything beyond that. Use other ways to=C2=A0 express such. If the compactness of expression written using=C2=A0 operators is everything you are interested in - define some=C2=A0 language and write a parser for it, and enjoy how short you can=C2=A0 express everything you need with it. You can even write such stuff directly in your D code and let=C2=A0 some string mixins massage it to compile.Or use C++ or Python which allow for this. Fine, end of D having a future amongst a large section of the programming population. This is fine. Unless D wants to be a player in this game.=C2=A0I can't see the point to relax the rules for operator overloading=C2=A0 unless you can show that they prevent parts of the original=C2=A0 design goal.This has already been done, read the thread. SQLAlchemy. The expression language is a a lovely builder DSL for constructing SQL entirely in Python with no parser overhead. No operator overloading, no DSL for builder languages. See same on the JVM: in Java you can't do it, Kotlin, Ceylon, Scala, Groovy, do it beautifully, and a lot of people do. Java only survives as a language for constructing new systems because a very large part of the Java programming community cannot be bothered to learn new stuff that doesn't have Java on the label. Even then many are not sure about this Java 8 thing. Indeed many are not even sure Java 5 was a good thing. Yes there are a lot of people still writing new stuff in Java 1.4.2 because generics, streams, modern programming techniques are new fangled syntactic sugar that is not needed to express the algorithm. I can give lots of anecdotal evidence on this drawn from workshops I have presented. The question here is whether D wants to include these sorts of things or reject them. But at the heart of the debate is whether a DIP will be evolved into a change to the D language or whether it will be rejected even before it is put together. --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Sep 30 2016
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 DavisIt'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.
Sep 30 2016
On Friday, September 30, 2016 12:31:45 Minty Fresh via Digitalmars-d wrote: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.Of course, you can write code that behaves badly. There's no way that that can be completely prevented while still allowing you to do useful, productive things. But the folks asking to be able to overload < separately just so that they can make it behave differently than what opCmp does are basically asking for a way to be allowed to make their code behave badly with the comparison operators in a way that opCmp doesn't currently allow. The request is to improve support for an idiom that many consider to be horrible coding practice, and Walter does not think that explicitly supporting such an idiom makes any sense. He hasn't gone to extra effort to prevent every possible misuse of overloaded operators that he could. He simply defined some of the overloaded operators in a way that was a significant improvement for the use case that he thought that overloaded operators should be used for, and as a side effect, it happens to have made it harder for a use case that he thinks is bad practice. I think that he made the right decision. But if you or anyone else wants to do wacky stuff with overloaded operators that is not consistent with the built-in types, you're free to do so within how D's overloaded operators work. You're just not going to be able to do it as freely as you can in C++, because that goes against the goals of the operator overloading feature in D, and some of the improvements that were in line with the goals happen to have gotten in the way of such operator overloading abuse. - Jonathan M Davis
Sep 30 2016
On Friday, 30 September 2016 at 16:25:45 UTC, Jonathan M Davis wrote:But if you or anyone else wants to do wacky stuff with overloaded operators that is not consistent with the built-in types, you're free to do so within how D's overloaded operators work. You're just not going to be able to do it as freely as you can in C++, because that goes against the goals of the operator overloading feature in D, and some of the improvements that were in line with the goals happen to have gotten in the way of such operator overloading abuse.In your arguments in favor of this limitation of operator overloading, you keep referring to these goals, of what operator overloads have been intended to do. You've stated and restated that same explanation even though it's completely unconvincing because while stating this intention you have failed entirely to justify it. How many people have to state it how many times in how many different ways before it gets through? These are stupid goals. They reflect intention that has no basis in reason, that has no basis in reality, that is a blindly-enforced dogma. It always would have been simpler if, in the first place, opBinary had caught comparison operators and opCmp and opEquals were omitted. Instead, those making the decisions went out of their way to impose these arbitrary limitations. If we can start now to untangle that mistake, it will make D more tenable for real-world code. And make no mistake: Perl is fantastic for real-world code because real-world code is not elegant, and it doesn't follow the rules, and it doesn't care how you meant for a feature to be used. Practical languages give the programmer a great deal of expressive power, and it's okay if the rules allow nonsense expressions because it's up to the programmer, not the language, to know what's nonsense and what's not.
Sep 30 2016
On Fri, 30 Sep 2016 19:33:33 +0000, pineapple wrote:How many people have to state it how many times in how many different ways before it gets through? These are stupid goals. They reflect intention that has no basis in reason, that has no basis in reality, that is a blindly-enforced dogma.More like: this is the common use case, so let's try to make that as smooth as possible, both for implementors and readers. And mucking about in the same area can add wrinkles that confuse people. The takeaway should be that we should exercise caution, not that we should refuse to change the language. But the basic idea does make sense. I'm not sure it's straightforward to make other operators consistent in the same way. You could try to enforce things like: typeof(a OP b) should be co/contravariant with typeof(a) or typeof(b) for math operators; opApply and opIndex should deal with the same types (though it's valid to add extras); that kind of thing. It does seem inconsistent that no attempt was made, but the language was only Walter Bright for nearly a decade, and one person doesn't have that much time. With most of the language and compiler work still being Walter Bright, he has much more say in the direction of the language than anyone else.It always would have been simpler if, in the first place, opBinary had caught comparison operators and opCmp and opEquals were omitted. Instead, those making the decisions went out of their way to impose these arbitrary limitations. If we can start now to untangle that mistake, it will make D more tenable for real-world code.That would have been tricky, or at least unpleasant, before auto return types. Auto return types were introduced after 2010, and opCmp was introduced before 2006.
Oct 01 2016
a.isLessThan(b)I understand the concern of possible mess due to unrestricted use of operator overloading (like C++). Java has clearly driven the point home by banning the operator overloading altogether. 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.
Sep 30 2016
On 01.10.2016 01:31, Sai wrote:I understand the concern of possible mess due to unrestricted use of operator overloading (like C++).C++ does it in std.
Sep 30 2016
On Fri, 2016-09-30 at 23:31 +0000, Sai via Digitalmars-d wrote:Genuine question: In the post Java languages, how many languages=C2=A0 allowed unrestricted operator overloading and did that cause any=C2=A0 similar mess?It is not feasible to provide a count, as there is always another language one forgot. Groovy, Kotlin, Ceylon, and Scala certainly allow operator overloading. Scala even allows new operator symbol definition. There are some incomprehensible Scala programs because of this. But then there are many incomprehensible D programs =E2=80=93 you can play code golf in any language. Just because there is a feature in a language doesn't mean it has to be abused. I cannot remember offhand whether Fantom, Golo, Gosu, etc. allow operator overloading. The core lesson of Python is that if you allow everything to happen, there can still be a base of excellent code. Paternalism/maternalism in programming languages is massively overrated. Youngsters will escape the constraints. In the case of D operator overloading restrictions to the glories (!) that is C++. --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Sep 30 2016
On Fri, 30 Sep 2016 23:31:19 +0000, Sai wrote:Genuine question: In the post Java languages, how many languages allowed unrestricted operator overloading and did that cause any similar mess?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. 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.
Oct 01 2016
On Sat, 2016-10-01 at 14:55 +0000, Chris Wright via Digitalmars-d wrote:Groovy doesn't allow you to overload comparison operators individually,=C2=A0 and probably most JVM languages likewise. This is to retain compatibility=C2=A0 with Java, which has `.compareTo()` instead of `isLessThan()` etc.Yes it does. =C2=A0http://groovy-lang.org/operators.html There is *also* compareTo.Ruby allows you to override individual comparison operators, with a=C2=A0 special operator `<=3D>` for combined comparisons. Nim lets you overload=C2=A0 arbitrary operators and create your own; some old discussions suggest=C2=A0 that the Comparable type is based on `<` alone.Groovy also supports the spaceship operator. --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Oct 01 2016
On Saturday, 1 October 2016 at 17:53:44 UTC, Russel Winder wrote:On Sat, 2016-10-01 at 14:55 +0000, Chris Wright via Digitalmars-d wrote:`<=>` 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.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.
Oct 02 2016
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.
Oct 01 2016
On 29.09.2016 18:41, Sai wrote:Not really, but it's annoying.I.e. you can overload '+' to do bad things. Yes, you can, and as I replied upthread that can be done because there's no way to prevent that while having operator overloading at all. But that is not justification for allowing such disasters for the comparison operators. I.e. one weakness is not justification for opening the door to all weakness.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? Wouldn't the current rules discourage someone from implementing CAS like library in D?
Sep 29 2016
On 2016-09-28 03:18, Minty Fresh wrote: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.I completely agree. Or we could go with an even more general approach: AST macros [1]. [1] http://wiki.dlang.org/DIP50 -- /Jacob Carlborg
Sep 27 2016
Me and Cauterite were toying with the idea of AST macros but in a completely new form a while ago. Below is the usage of it. Something you'll notice about it is that it could turn the asm block into a library solution (which is clearly what we'd want anyway). Not to mention Linq style queries. In theory it shouldn't be too complex to implement since you are only doing basic checks to determine if to parse the given statement / block to a rewriter function. ```D void main() { // \/ parsed by iasm.c by matches {}'s and sending contents to it asm { ... } import linq; Linq DataSource source = ...; Tree[] trees = source.trees.where(name = "abc").limit(20); import Assembly_x86; asm { ... } } struct Linq { string __ast(OnType, ExpectedType)(string statement) { assert(statement == "source.trees.where(name = "abc").limit(20);"); static assert(OnType == DataSource); static assert(ExpectedType == Tree[]); } } // Assembly_x86.d struct X86 {} struct ASM { string __ast(OnType, ExpectedType)(string statement) { assert(statement == "asm {\n ...\n };"); static assert(OnType == X86); static assert(ExpectedType == void); } } ASM X86 asm; ```
Sep 29 2016
On 2016-09-29 14:57, rikki cattermole wrote:Me and Cauterite were toying with the idea of AST macros but in a completely new form a while ago. Below is the usage of it. Something you'll notice about it is that it could turn the asm block into a library solution (which is clearly what we'd want anyway). Not to mention Linq style queries. In theory it shouldn't be too complex to implement since you are only doing basic checks to determine if to parse the given statement / block to a rewriter function. ```D void main() { // \/ parsed by iasm.c by matches {}'s and sending contents to it asm { ... } import linq; Linq DataSource source = ...; Tree[] trees = source.trees.where(name = "abc").limit(20); import Assembly_x86; asm { ... } } struct Linq { string __ast(OnType, ExpectedType)(string statement) { assert(statement == "source.trees.where(name = "abc").limit(20);"); static assert(OnType == DataSource); static assert(ExpectedType == Tree[]); } } // Assembly_x86.d struct X86 {} struct ASM { string __ast(OnType, ExpectedType)(string statement) { assert(statement == "asm {\n ...\n };"); static assert(OnType == X86); static assert(ExpectedType == void); } } ASM X86 asm; ```Hmm, I find this to be somewhat difficult to follow. You get the AST as a string? Which means you need to implement a parser. How will the macro invocation be transformed? Return a string from the macro which will be reparsed by the compiler and inserted at the call site? -- /Jacob Carlborg
Sep 29 2016
On 30/09/2016 2:18 AM, Jacob Carlborg wrote:On 2016-09-29 14:57, rikki cattermole wrote:I'll expand on what I wrote above. There are two kinds of invocations here. Blocks and statements. Statements are the type of thing you expect from e.g. Linq. Where as blocks would be what asm would be defined as being. The invocation defines where the start/end of the input file to be passed to __ast is and that is all it does. In each case, if the first token (or for assignment statements the first token of the expression) is a variable that happens to have a UDA on it with __ast member it will pass said invocation text directly to it. What ever that may be. As far as guarantees go for the input, it will always end in a semicolon. To determine if it was a statement vs a block just check if ExpectedType is void. So something like: ```D Linq DataSource source = ...; Tree[] trees = source.trees.where(name = "abc").limit(20); ``` Could be transformed into: ```D Linq DataSource source = ...; Tree[] trees = mixin(__traits(getAttributes, source)[0].__ast("source.trees.where(name = "abc").limit(20);")); ``` They key here is explicitly marking non-vanilla-D-code as such without adding syntax like ``macro{ stuff here }``.Me and Cauterite were toying with the idea of AST macros but in a completely new form a while ago. Below is the usage of it. Something you'll notice about it is that it could turn the asm block into a library solution (which is clearly what we'd want anyway). Not to mention Linq style queries. In theory it shouldn't be too complex to implement since you are only doing basic checks to determine if to parse the given statement / block to a rewriter function. ```D void main() { // \/ parsed by iasm.c by matches {}'s and sending contents to it asm { ... } import linq; Linq DataSource source = ...; Tree[] trees = source.trees.where(name = "abc").limit(20); import Assembly_x86; asm { ... } } struct Linq { string __ast(OnType, ExpectedType)(string statement) { assert(statement == "source.trees.where(name = "abc").limit(20);"); static assert(OnType == DataSource); static assert(ExpectedType == Tree[]); } } // Assembly_x86.d struct X86 {} struct ASM { string __ast(OnType, ExpectedType)(string statement) { assert(statement == "asm {\n ...\n };"); static assert(OnType == X86); static assert(ExpectedType == void); } } ASM X86 asm; ```Hmm, I find this to be somewhat difficult to follow. You get the AST as a string? Which means you need to implement a parser. How will the macro invocation be transformed? Return a string from the macro which will be reparsed by the compiler and inserted at the call site?
Sep 29 2016
On Wednesday, 28 September 2016 at 01:18:58 UTC, Minty Fresh wrote: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. [...]opCmp was a good idea. Allowing opBinary to bypass opCmp is also a good idea. Atila
Oct 02 2016