September 30, 2016
On 30/09/2016 2:18 AM, Jacob Carlborg wrote:
> 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?

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 }``.
September 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?


September 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)

September 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:
> > 
> > If I understand the issue correctly, one will not be able to
> > overload <=, >, etc
> > for symbolic math, like CAS (mimicking mathematica for example),
> > how can I do it
> > now?
> 
> 
>     a.isLessThan(b)

How wonderfully Java.

-- 
Russel. ============================================================================= Dr Russel Winder      t: +44 20 7585 2200   voip: sip:russel.winder@ekiga.net 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

September 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:
>> On 9/29/2016 9:41 AM, Sai wrote:
>> > 
>> > If I understand the issue correctly, one will not be able to
>> > overload <=, >, etc
>> > for symbolic math, like CAS (mimicking mathematica for example),
>> > how can I do it
>> > now?
>> 
>> 
>>     a.isLessThan(b)
>
> How wonderfully Java.

Personally, I'm amused because this implies the prospect of:

  a.isGreaterThanOrEqualTo(b)

I mean, there is an acceptable level of verbosity. This is not it.
September 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:
> > On Thu, 2016-09-29 at 10:52 -0700, Walter Bright via
> >
> > Digitalmars-d wrote:
> >> On 9/29/2016 9:41 AM, Sai wrote:
> >> > If I understand the issue correctly, one will not be able to
> >> > overload <=, >, etc
> >> > for symbolic math, like CAS (mimicking mathematica for
> >> > example),
> >> > how can I do it
> >> > now?
> >>
> >>     a.isLessThan(b)
> >
> > How wonderfully Java.
>
> Personally, I'm amused because this implies the prospect of:
>
>    a.isGreaterThanOrEqualTo(b)
>
> I mean, there is an acceptable level of verbosity. This is not it.

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 Davis

September 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 Davis

Also with mixins and a CTFE D parser you could replace the operators by any desired function calls.


September 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".

September 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.
September 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:
> > 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".

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 Davis