April 14, 2020
On Tuesday, 14 April 2020 at 12:28:00 UTC, Steven Schveighoffer wrote:

> Without knowing what castTo is supposed to do, if I saw s.castTo = i, I would not expect at all that i is going to change.

What would you expect when you see
```
  i  ._=  s;
```
which is also currently legal code in Dlang?
April 15, 2020
On Tuesday, 14 April 2020 at 12:28:00 UTC, Steven Schveighoffer wrote:
> On 4/14/20 2:44 AM, Manfred Nowak wrote:
>> On Tuesday, 14 April 2020 at 06:10:33 UTC, Steven Schveighoffer wrote:
>>> Note that at this time, only one alias this is allowed per structure.
>> 
>> This restriction falls by the suggested scheme:
>> 
>> ```
>> struct S{
>>    string data;
>>      import std.conv: to;
>>    void castTo( ref int arg){
>>      arg= to!int( data);
>>    }
>>    void castTo( ref string arg){
>>      arg= data;
>>    }
>> }
>> void main(){
>>    auto s= S( "42");
>> 
>>    int i;
>>    s.castTo =i;
>> 
>>    string str;
>>    s.castTo =str;
>> 
>>      import std.stdio;
>>    writeln( i, ":", str); // 42:42
>> }
>> ```
>
> Yes, I was responding to the point talking about opImplicitCast. Instead of that, we got alias this.
>
> Proposals have been started to add multiple alias this. I think many consider alias this in general to be a troublesome feature that could have been done better. I don't know what will happen with it.
>
> I would recommend not using the = syntax to denote the opposite of what it normally means (that the rhs is being assigned). You are better off I think just calling it like a function:
>
> s.castTo(i);
> s.castTo(str);
>
> Without knowing what castTo is supposed to do, if I saw s.castTo = i, I would not expect at all that i is going to change.
>
> -Steve

I consider alias this to be a mistake. There are simply too many bugs for it, as it does more than implicit conversion. The dlang would be better off if it were to implement opImplicitCast for lvalues while implicit constructors for rvalues. While putting alias this into maintenance mode, and discouraging future use of it.
We make it opt-in for functions to avoid the same mistake as c++ did.
April 15, 2020
On Tuesday, 14 April 2020 at 21:45:22 UTC, Manfred Nowak wrote:
> On Tuesday, 14 April 2020 at 13:03:19 UTC, aliak wrote:
>> Also, you can make it a generic free function if you want.
> [...]
>> i.castAssign(s); // cast and assign s
>
> And because the pair of parenthesis can by exchanged by a `=', giving
>   `i   .castAssign=   s;'
> you just evaluated, that there is in addition to  {+, -, *, /, %, ^^, &, |, ^, <<, >>, >>>, ~} an additional bunch of ops for the op-assignment-operator giving the resulting form in regular language parlor:
>   '.' ident '='
>
> Allowing ident to be an empty string would even include `.=' to be recognized as an assignment operator. This is very close to the assignment operator in pascal `:='.
>
> What is the better annotation of a coder knowing, that a cast is being executed under the hood: `._=' or `:='?

I don't think either of those tell me about a cast happening. Maaaaaybe .cast= but I'm not sure and it feels weird.

April 15, 2020
On Wednesday, 15 April 2020 at 07:44:23 UTC, aliak wrote:
> [...] it feels weird.

Yes. But `._=' is legal Dlang.

In C one would have to annotate the possibility of writing to a parameter by using `&' to get the address of the variable.

Would the legal Dlang phrase `._=&' make the intention more clear?

------

struct S{
  string data;
    import std.conv: to;
  void _( ref int arg){
    arg= to!int( data) *10;
  }
  void _( real* arg){
    *arg= to!real( data) *10 +1;
  }
}
void main(){
  auto s= S( "42");

  int i;
  s  ._=  i;

  real r;
  s  ._=&  r;

    import std.stdio;
  writeln( i, ":", r); // 420:421
}
April 15, 2020
On Wednesday, 15 April 2020 at 09:56:02 UTC, Manfred Nowak wrote:
> On Wednesday, 15 April 2020 at 07:44:23 UTC, aliak wrote:
>> [...] it feels weird.
>
> Yes. But `._=' is legal Dlang.

Yes, but I'm not sure what the legality of syntax has to do with readability/maintainability/etc?

>
> In C one would have to annotate the possibility of writing to a parameter by using `&' to get the address of the variable.
>
> Would the legal Dlang phrase `._=&' make the intention more clear?

Not to me.

Custom operators are generally very hard to get right. It's one of D's good decisions to limit them (not that they're perfect, there are still inconsistencies to fix but aside from that, they are a good decision)

Elm recently (well, last year or two was it?) did away with allowing cryptic operators as well and there's a writeup by Elm's author: https://gist.github.com/evancz/769bba8abb9ddc3bf81d69fa80cc76b1



>
> ------
>
> struct S{
>   string data;
>     import std.conv: to;
>   void _( ref int arg){
>     arg= to!int( data) *10;
>   }
>   void _( real* arg){
>     *arg= to!real( data) *10 +1;
>   }
> }
> void main(){
>   auto s= S( "42");
>
>   int i;
>   s  ._=  i;
>
>   real r;
>   s  ._=&  r;
>
>     import std.stdio;
>   writeln( i, ":", r); // 420:421
> }


April 15, 2020
On Wednesday, 15 April 2020 at 09:56:02 UTC, Manfred Nowak wrote:
> On Wednesday, 15 April 2020 at 07:44:23 UTC, aliak wrote:
>> [...] it feels weird.
>
> Yes. But `._=' is legal Dlang.
>
> In C one would have to annotate the possibility of writing to a parameter by using `&' to get the address of the variable.
>
> Would the legal Dlang phrase `._=&' make the intention more clear?

If you want to communicate the meaning of your code to other D programmers, the clearest way to do it is to use language features whose meaning they already know and understand:

lhs = cast(typeof(lhs)) rhs;

If that's unacceptable, the next clearest way is to use words:

lhs.castAssign(rhs);

If you insist on inventing a new symbol, no one will understand it without being taught. That's how symbols work. Just like you didn't know what + and × meant until you learned them in school, no one reading your code will know what `._=` means until they learn it by reading your documentation.
April 15, 2020
On Wednesday, 15 April 2020 at 12:30:43 UTC, aliak wrote:
> Yes, but I'm not sure what the legality of syntax has to do
> with readability/maintainability/etc?
That depends ... When character sequences, legal in a programming language, are causing disgust, then that language might have a design flaw not detectable by their _usual_ users.

> Elm recently (well, last year or two was it?) did away with allowing cryptic operators [...]
On the other hand there still is seed7-lang (https://en.wikipedia.org/wiki/Seed7) claiming, that in addition to operators the whole syntax is under control of the coder.

The root of failing to detect intention stems from structuring and partly hiding data. Structuring raises the need to somehow access the data stored within the structure, mainly done by qualifying the identifiers `s.i'. Partly hiding then raises the need to access the data via _other_ qualified identifiers, which are not hidden like `s.isNull', `s.nullify', `s.set( val)' ...

Of course using any of those newly introduced identifiers implicitly calls a function, whose outcome the coder has to know; otherwise the coder is unable to implement his own intentions.

Answers this enough of your question I cited at the beginning of this post?
April 15, 2020
On Wednesday, 15 April 2020 at 14:42:11 UTC, Paul Backus wrote:
> If that's unacceptable, the next clearest way is to use words:
>   lhs.castAssign(rhs);
> If you insist on inventing a new symbol, [...]

I don't.

As well as it is legal Dlang to write your
    lhs.castAssign(rhs)
it is legal Dlang to write
    lhs._(rhs);
or
    lhs._ = rhs;
or
    rhs.castAssignToParameterByUsingLongWord(lhs);

As long as the used identifiers have no predefined and unchangeable meaning every reader will anyway have to lookup the meaning of a particular identifier. Usually software engineers have the duty to build the dictionary for that lookup and it is the duty of the language to shield that dictionary against changes.

But in Dlang even unchanged operators have no fixed meaning. For this please look for restrictions in the specs for the overloading of the assignment operator (https://dlang.org/spec/operatoroverloading.html#assignment).

One might recognize, that there are no restrictions for structs. Therefore it is legal for an instance `lhs' of a struct to write
    lhs = rhs;
and thereby de facto assigning to the variable rhs.

Please note that the second requirement for
(https://dlang.org/spec/expression.html#assignment_operator_expressions)
is fulfilled too.


---
struct S{
  int data;
  void opAssign( ref int arg){
    arg= data;
  }
}
void main(){
  auto s= S( 42);
  int i= 101;
  s = i;

    import std.stdio;
  writeln( i); // 42
}

April 15, 2020
On Wed, Apr 15, 2020 at 04:56:35PM +0000, Manfred Nowak via Digitalmars-d wrote: [...]
> But in Dlang even unchanged operators have no fixed meaning.
[...]
> One might recognize, that there are no restrictions for structs.
> Therefore it is legal for an instance `lhs' of a struct to write
>     lhs = rhs;
> and thereby de facto assigning to the variable rhs.

This is precisely the kind of operator overloading abuse that Walter does not like, and which led to the ==, <, >, etc., operators not being overloadable individually, but only via opEquals and opCmp, as a measure to ensure some level of consistency in the meaning of the operators. It's not a perfect measure, of course, and the spec does not prevent every possible case of abuse that fulfills the letter of the spec but not the spirit, but that's only because it will also prevent useful applications of operator overloading, rather than an endorsement of this sort of operator abuse.

Custom operators have repeatedly been proposed, and Walter's stance has always been that if you need unusual operators you should just use a DSL in a string mixin instead of altering the meaning of the language's surface syntax.

Certainly, it's *possible* to overload opAssign such that `lhs = rhs;` assigns to rhs instead of lhs, but this sort of operator abuse leads to code becoming unreadable and unmaintainable because nobody knows what the surface syntax means anymore, like the hellhole of C++'s free-for-all, every-man-for-himself wild-wild-west operator overloading abuse where the following code can have completely divergent *parse trees*:

	fun<A, B>(a, b);
	gun<T, U>(a, b);

Think you know that these two lines mean?  Think again. See them in context:

	// Totally evil example of why C++ template syntax and
	// free-for-all operator overloading is a Bad, Bad Idea.
	#include <iostream>
	struct Bad { };
	struct B { };
	struct A {
		Bad operator,(B b) { return Bad(); }
	};
	struct D { };
	struct Ugly {
		D operator>(Bad b) { return D(); }
	} U;
	struct Terrible { } T;
	struct Evil {
		~Evil() {
			std::cout << "Hard drive reformatted." << std::endl;
		}
	};
	struct Nasty {
		Evil operator,(D d) { return Evil(); }
	};
	struct Idea {
		void operator()(A a, B b) {
			std::cout << "Good idea, data saved." << std::endl;
		}
		Nasty operator<(Terrible t) { return Nasty(); }
	} gun;
	template<typename T, typename U>
	void fun(A a, B b) {
		std::cout << "Have fun!" << std::endl;
	}
	int main() {
		A a;
		B b;

		// What do these lines do?
		fun<A, B>(a, b);
		gun<T, U>(a, b);
	}

You can argue all you want that the programmer ought to read and memorize all 1400+ pages of C++ spec plus however many hundreds of local project worth of docs in order to know what he's doing, but at the end of the day, this is just a huge waste of time and effort just so that the original code author can save a few keystrokes.  The technical debt incurred is completely disproportionate with the meager benefits, and IMO makes no sense.  Why go out of your way to make your code harder to read and maintain -- as if programming itself isn't already complex enough that basically every project has hundreds and thousands of bugs that will require so much effort to fix -- when you could just spend another 1/2 a second to type a few more keystrokes and make the code immediately understandable to anyone with a competent grasp of D?

(Of course, if this is a personal project, then sure, go crazy and do whatever you want, I don't care.  Just be warned that the code *will* be completely unmaintainable by anyone else -- and by "anyone else" I mean yourself after 5 months. :-P  Speaking from experience here, btw. I've been down that road, and I can tell you that it does not lead to a good place, regardless of all initial appearances.)


T

-- 
In order to understand recursion you must first understand recursion.
April 15, 2020
On Wednesday, 15 April 2020 at 17:22:51 UTC, H. S. Teoh wrote:
> This is precisely the kind of operator overloading abuse
[...]
> make the code immediately understandable to anyone with a competent grasp of D?

Agreed and refusing to follow the content of the subject further.