Thread overview
[Issue 14593] operator overloading can't be used with expression templates
Jun 16, 2015
Walter Bright
Jun 17, 2015
Igor Stepanov
Sep 10, 2015
Martin Nowak
Sep 10, 2015
Martin Nowak
Sep 13, 2015
Artem Borisovskiy
Dec 17, 2022
Iain Buclaw
June 10, 2015
https://issues.dlang.org/show_bug.cgi?id=14593

Andrei Alexandrescu <andrei@erdani.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Version|unspecified                 |D2

--
June 16, 2015
https://issues.dlang.org/show_bug.cgi?id=14593

Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
                 CC|                            |bugzilla@digitalmars.com
           Hardware|Other                       |All
         Resolution|---                         |WONTFIX

--- Comment #1 from Walter Bright <bugzilla@digitalmars.com> ---
Using expression templates to implement DSL's makes code really hard to understand and debug. There are better ways.

--
June 17, 2015
https://issues.dlang.org/show_bug.cgi?id=14593

Igor Stepanov <wazar.leollone@yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |wazar.leollone@yahoo.com

--- Comment #2 from Igor Stepanov <wazar.leollone@yahoo.com> ---
(In reply to Martin Nowak from comment #0)
> A motivating example is using expression templates to specify db queries.
> 
> db.get!Person.where!(p => p.age > 21 && p.name == "Peter")
> 
> This has the following problems:
> - opCmp doesn't allow to capture the op
> - it's not possible to overload &&
> - opEquals must return a bool (but here it needs to return p)
> 
> A solution would be to use the generic opBinary for < <= > >= == iff opCmp/opEquals don't exist and also extending it to && ||.

(In reply to Walter Bright from comment #1)
> Using expression templates to implement DSL's makes code really hard to understand and debug. There are better ways.

+1
You may pass where condition as string, and use libdparse, or something like it
to build AST and compile it to your SQL expression.
db.get!Person.where!(`p.age > 21 && p.name == "Peter"`)
This looks not worse, and at the same time, more honest.
BTW, if we will implement .astof property, which returns AST of
expression/symbol (without possibility to generate new symbol from existing AST
it will not be macros), we will able to use compiler to generate AST of this
expression:

template AstOf(string expr)
{
    enum AstOf = mixin(expr).astof;
}

--
September 10, 2015
https://issues.dlang.org/show_bug.cgi?id=14593

Martin Nowak <code@dawg.eu> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
         Resolution|WONTFIX                     |---

--- Comment #3 from Martin Nowak <code@dawg.eu> ---
(In reply to Walter Bright from comment #1)
> Using expression templates to implement DSL's makes code really hard to understand and debug.

I'm not advocating complex DSLs but there are a number of areas where
expression templates are the natural choice (matrix, vector, simd ops) b/c the
compiler already typechecks and does the usual operator precedence.
You even recommended that yourself here
https://github.com/D-Programming-Language/druntime/pull/471#issuecomment-16092197.

> There are better ways.

If you want to see one "better" way, look at MongoDB which named operators instead of normal JS expressions.

db.inventory.find(
   {
     type: 'food',
     $or: [ { qty: { $gt: 100 } }, { price: { $lt: 9.95 } } ]
   }
)

> You may pass where condition as string, and use libdparse, or something like it to build AST and compile it to your SQL expression.
db.get!Person.where!(`p.age > 21 && p.name == "Peter"`) This looks not worse, and at the same time, more honest.

I'd have to use a complex CTFE parser implementation to get the AST. And then I'd still have to perform semantic analysis (bind names) and run typechecks, this is fairly unfeasible.

The requested opBinary extension is a very small language addition and allows for more efficient operators in general (opBinary!"<" vs. opCmp). Please reconsider the decision.

--
September 10, 2015
https://issues.dlang.org/show_bug.cgi?id=14593

--- Comment #4 from Martin Nowak <code@dawg.eu> ---
The worst with string arguments is that they can't use variables from the calling scope.

--
September 13, 2015
https://issues.dlang.org/show_bug.cgi?id=14593

Artem Borisovskiy <kolos80@bk.ru> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |kolos80@bk.ru

--- Comment #5 from Artem Borisovskiy <kolos80@bk.ru> ---
(In reply to Martin Nowak from comment #4)
> The worst with string arguments is that they can't use variables from the calling scope.

Let's admit it: string mixins are just slightly better preprocessor macros. They sometimes save time, indeed, but there is no D IDE sufficiently smart to expand and semantically analyse them, they're hard to debug, compiler messages don't help much (because we can't see the actual generated code), and code generation for mixins looks messy most of the time, since it usually is just string concatenation. Even if we decide to use format() for prettier string generation, we will immediately have another problem to solve - how to generate code, which itself uses formatting. We can escape %'s, but it looks just as messy as regular expressions in double-quoted strings, and it's too easy to forget to do that. Another problem is parsing a DSL: we can't count on tokenized strings, since there's no way to enforce their usage on the call site, therefore we must even tokenize DSL by hand.

AST macros are the only robust _and_ convenient way to generate arbitrary code, and since we don't have them, we should invent other ways, instead of sticking string mixins everywhere and turning our pretty D code into something looking even worse than C preprocessor magic: at least, in C you don't need to concatenate anything most of the time.

I'm not sure whether it should be done with operator overloading, but I like your DB query example, it looks intuitive and clean.

(In reply to Walter Bright from comment #1)
> Using expression templates to implement DSL's makes code really hard to understand and debug. There are better ways.

So do string mixins. What are the other ways? It would be great to have a DSL with maximum assistance from the compiler, i.e. with type checking and minimum boilerplate. How to implement an inline assembler without using string mixins or poking the compiler's guts, for example? We should do better than 40-year old Scheme, otherwise the terrorists (syntactic ones) have won.

--
December 17, 2022
https://issues.dlang.org/show_bug.cgi?id=14593

Iain Buclaw <ibuclaw@gdcproject.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Priority|P1                          |P4

--
December 13
https://issues.dlang.org/show_bug.cgi?id=14593

--- Comment #6 from dlangBugzillaToGithub <robert.schadek@posteo.de> ---
THIS ISSUE HAS BEEN MOVED TO GITHUB

https://github.com/dlang/dmd/issues/17708

DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB

--