April 21, 2005
On Thu, 21 Apr 2005 17:28:03 +0000 (UTC), pragma <pragma_member@pathlink.com> wrote:
> In article <d48je6$arv$1@digitaldaemon.com>, TechnoZeus says...
>>
>> If the programmer wants to be sure that they are assigning values, and not changing the address of somehting, then the ":=" operator would be used...
>>
>> int a := 5;
>> int b;
>> int c;
>> b := a+7;
>> c := b;
>>
>> No ambiguity there.  Notice that with this convention, one would know what "a := b" is supposed to do,
>> even without knowing what "a" and "b" represent.  The same can not be said of "a = b" in D.
>>
>
> The problem with your example in this argument is that it's ambiguous.
>
> b := a+7
>
> Does it mean "take the actual value of the lvalue"?

It means call: b.opAssign(a+7);

Regan
April 21, 2005
>> The problem with your example in this argument is that it's ambiguous.
>>
>> b := a+7
>>
>> Does it mean "take the actual value of the lvalue"?
> 
> 
> It means call: b.opAssign(a+7);
> 
> Regan

Which, is exactly the same as regular "=" precidence, ie the assignment operation always happens last.

Brad
April 21, 2005
"Vladimir" <kv11111@mail.ru> wrote in message news:d492pb$p4h$1@digitaldaemon.com...
> Ben Hinkle wrote:
>> I'd like to see more motivating examples of what the problems are and
>> what
>> the workarounds look like. Sometimes the cure is worse than the disease.
>
> One of examples you can find at the end of my post in different branch of this thread: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/22137

A complete example from an actual project was what I had in mind. The posted example wasn't complete and the purpose didn't make sense to me. There were many issues hidden under the dots (...) that would be nice to see.

> Of course there are workarounds, but they are ugly and error-prone.

Two versions (one for Object and one for everything else) seems reasonable to me. It depends on the template. If there is alot of code shared between the templates mixins can help factor it out.

> The biggest problems occurs when one tries to make template from
> non-template function. Or when one had written and tested template and
> then
> realized that it won't work with his new class-based type and should be
> rewritten. And this can't be solved with .dup() property.

Can you give a more complete example? I'm assume this happened to you for real.

<flame-alert>
> BTW in C++ this example can be _easily_ implemented.

I assume you mean because classes have value semantics in C++. I'd say C++
templates are more error-prone than D templates due to all the magic in C++
templates.
</flame-alert>


April 21, 2005
> 
> Can you give a more complete example? I'm assume this happened to you for real.
> 
I haven't written this yet, but I am pretty sure it is impossible:
A template that implements a linked list (or any other container), such that when you add an object to the list it copies the object.  You may want to do this so you can roll back the state of your program, ie an undo button.
There are 2 problems with this
1) Doesn't work with both references and builtings/structs
2) No language specified way to work around it, so you have to cook your own .dup property, or whatever - but it won't work with classes that don't provide that custom function.  You could standardize on using copy constructor - but builtins and structs don't have them.

So there we go - a templated linked list that copies the objects added to it is impossible in D.  If I am wrong - please enlighten me :)

Brad
April 21, 2005
brad beveridge wrote:
> Vladimir wrote:
> <snip>
> Vladimir - that is a fantastic example of the disconnect between reference types and value types, and how screwed up you could potentially get with templates.  You've also illustrated that the := operator doesn't really cut it in terms of making life better.
> Can we come up with something that fixes this?

This post essentially sums up what I've been talking about for some time.

1) It is obvious that the difference between reference and value assignment does cause head aches. (For the non-gurus anyway. :-) )

2) All of the discussion about "=" vs "==" (etc.) has actually been about this single issue (whether all the participants have realised it, or not.)

3) There seems not to exist an obvious solution, at least as far as we've got so far.

4) For all I know, there might not even exist a problem here. (!) OTOH, this does seem to be a thing that gets peoples' attention, and does seem to disturb people -- even if they come from C++ or Java. (Those coming from other languages, I'd _expect_ to get stuck with this issue.)

5) Considering that D is a "metal near language" (in the spirit of C), and a high level language (in the spirit of C++ and Java -- but not ever aspiring to the level of Lisp), it is natural, that this distinction is prominent in the language -- after all, the distinction is very visible in assembler and C. (And in processor architecture.)

6) As a side effect of this, the discussion of .value and .reference, as well as (a part of) the discussion of comparability vs. equality, has arisen.

On the surface, there would exist a number of "solutions".

 - Create two distinct assignment operators.

   - := and =.

     - Have each do its part, and only then default to the other.

     - Have each do its part, and fail when applied wrong.

     - Have a war about which does which.

 - Somehow else separate value and reference assignment.

     - Using & or some other syntactic means.

     - Rely on the lvalue accepting only either.

I could go on with this list, as anybody else could, too. But what I see here is, a lack of a common understanding and thorough insight between the two. Therefore, I suggest that we refrain from "Calling Walter" for quite some time with this issue.

We really need to get to the bottom of this. (We might find nothing of value -- whence the existing status quo would suffice. Or, we might find something else, but then we'd know exactly what we want! By that time it would be "a piece of cake" to ask Walter to pay attention.)

So far, however, this discussion (excuse me, everybody) hasn't turned up anything "new". Hey, I'm not putting any single person down, or the entire discussion. I'm just (like a referee, this time) "lifting the cat on the table" as we say in Finland, or writing the obvious on the wall.

-----

I do (whaddayaknow) humbly admit here, that I haven't got a clear picture of the issue, so far. Somehow I "feel" that the distinction between value and reference, is, eh, unsharp. (Not as a concept, but as it is implemented in the _syntax_ (or, more to the point, the _semantics_) of quite a few languages, including D.)

On one hand, I'd love a situation where there were two separate assignment operators (for example := and =), where neither would accept the "wrong" kind of rvalue nor lvalue.

On the other hand, I feel that this would make programming cumbersome, introduce gratuituous obstacles, steer folks' attention to undeserving detail, and appear low-level upon the whole.

-----

The distinction between value and reference is (to my (this time) not so humble opinion), very much less clear to the newcomer in D, as it is in C. The same problem occurred to me when initially learning Pascal. (Where it was actually less opaque than in D.)

While people hate pointers and references in C, at least they are consistent (in _this_ respect, not necessarily in general).

So, this discussion does carry some merit, IMHO.

  But let's not assume this is for D 1.0!!!

  Let's all accept that this discussion is about
  something bigger, and more fundamental, and
  therefore we'd be stupid to ecxpect that we'd
  reach the required level of common (or even
  individual) understanding before D 1.0
  has been out for a long time.

While I'm not suggesting that we get rid of imports or the need to write the main function (for the illiterate, see other thread), I do think that this issue is worth some serious study.
April 21, 2005
>>Hmm, isn't there a problem that if you do
>>
>>func(T a)
>>{
>>     T b:=a;
>>}
>>
>>b is null if T is reference-type, so it can't even have the value
>>assigned? You can't explicitly new it, because that wouldn't work with
>>primitive types again.
>>
>>It could get automatically allocated, but that'd require the class to
>>have a zero-parameter constructor, which may again break, and in fact,
>>calling it may cause unforeseen effects.
> 
> Please, look at my post in different branch of this thread:
> http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/22165

With .init on classes:
- all uninitialized vars of a class will point to the same object
- using := with any of them will change all the others
- so, even trivial code like

func(T a, T b)
{
T c:=a+b;
T d:=a*b;

return c/d;
}

will totally not work, because after the second line, c will have the same value as d, so the result will always be the same (1, assuming some normal numeric class). In a multithreaded app, things will get even uglier, because c and d may get modified from outside, which is not the case with =.


xs0
April 21, 2005
Georg Wrede wrote:
<snip>
> 
> The distinction between value and reference is (to my (this time) not so humble opinion), very much less clear to the newcomer in D, as it is in C. The same problem occurred to me when initially learning Pascal. (Where it was actually less opaque than in D.)
> 
> While people hate pointers and references in C, at least they are consistent (in _this_ respect, not necessarily in general).
> 
> So, this discussion does carry some merit, IMHO.
>
<snip>
Excellent post Georg - and precisely the reason that I suggested "Walter Weigh In"s should first be sanctioned by senior members.  We obviously haven't covered enough ground with this topic yet.  As you say, the distinction between reference and value in D are not very clear - I personally think that such a fundamental concept should be clarified/fixed before v1.0 - but that is just IMHO.
I'm afraid that I can't offer much more to this thread, so hopefully smarter people than me will figure something out.  I must also say that I haven't personally run into this problem yet.  Can someone who has run into this problem in real code make a post - otherwise we are simply intellectualising (and D is a practical language, not an acedemic one).
I know that Derek wanted to convert one object to another, and that is possibly where the := operator stemed from, but other than that I don't think anyone else has posted about running into this in real life.

Brad
April 21, 2005
"Brad Beveridge" <brad@somewhere.net> wrote in message news:d495k4$rrl$1@digitaldaemon.com...
>
>>
>> Can you give a more complete example? I'm assume this happened to you for real.
>>
> I haven't written this yet, but I am pretty sure it is impossible:
> A template that implements a linked list (or any other container), such
> that when you add an object to the list it copies the object.  You may
> want to do this so you can roll back the state of your program, ie an undo
> button.
> There are 2 problems with this
> 1) Doesn't work with both references and builtings/structs
> 2) No language specified way to work around it, so you have to cook your
> own .dup property, or whatever - but it won't work with classes that don't
> provide that custom function.  You could standardize on using copy
> constructor - but builtins and structs don't have them.

My first reaction is that the simplest solution is to use a regular linked list and have either the calling code dup whatever they needs to be dup'ed. The user knows their objects the best and how to handle the references so keeping the linked list as simple as possible makes them more usable. Why have something as simple as a linked list try to worry about duplicating the objects in the list? That shouldn't be its job.

If it really is needed to make the list copy the objects I'd try writing a template with different specializations that share code for common actions. Since Object doesn't have any dup property the templates would only work for objects that define some form of duplication.

> So there we go - a templated linked list that copies the objects added to it is impossible in D.  If I am wrong - please enlighten me :)

If you mean in a single template then I agree. I wasn't asking for examples because I didn't think it was impossible. I was asking for examples to see what the problem is, what the workarounds look like and how := would be any better than various other solutions. The general topic of writing templates that works with reference and value types has come up before (probably many times) and dup or := or whatever is one piece of the bigger picture.

In any case IMO this whole thread should wait until after 1.0.


April 22, 2005
On Fri, 22 Apr 2005 10:49:45 +1200, Brad Beveridge wrote:


[snip]
> I know that Derek wanted to convert one object to another, and that is possibly where the := operator stemed from, but other than that I don't think anyone else has posted about running into this in real life.

BTW, I've resigned myself to using a 'Value' property in the classes I'm working with, as I can't see Walter bothering to make coding any easier for us  ...

  class Foo
  {
      void Value(Bar x) { ... }
  }

  class Bar
  {
      void Value(Foo x) { ... }
  }

  Foo f = new Foo;
  Bar b = new Bar;

  Foo.Value = b;
  Bar.Value = f;


-- 
Derek
Melbourne, Australia
22/04/2005 10:55:07 AM
April 22, 2005
>  class Foo
>  {
>      void Value(Bar x) { ... }
>  }
>
>  class Bar
>  {
>      void Value(Foo x) { ... }
>  }
>
>  Foo f = new Foo;
>  Bar b = new Bar;
>
>  Foo.Value = b;
>  Bar.Value = f;

Without knowing anything about the context, would using toFoo and toBar work? I use toFoo to "cast" to other types much like toString takes the object and returns a string.

class Foo
  {
      Bar toBar() { ... }
  }

  class Bar
  {
      Foo toFoo() { ... }
  }

  Foo f = new Foo;
  Bar b = new Bar;

  Foo f2 = b.toFoo();
  Bar b2 = f.toBar();

Note the original example Foo.Value = b doesn't compile - I assume you meant something like f.Value = b.