www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - How to bridge the gap between user defined types and built in types?

reply brad domain.invalid writes:
I think this needs a new thread.  Here is a snip of what I previously 
posted...


I got to thinking about what languages try to achieve with allowing 
operator overloading, I think that they try to make user defined types 
behave exactly as intrinsics.  This is especially important for a 
language that allows templates, as your templates should work with built 
in types and user defined types.  A while ago Derek ran across a problem 
   (thread title "opValue()") where his templates wouldn't work with 
aggregates because "=" does a reference copy, when he infact wanted a 
deep copy.
I think that this is a similar problem - do programmers want their 
operators to do a reference compare, or a deep compare?

In thinking along these lines I realised that D (at the moment) does not 
allow you to create user defined types that behave exactly as built in 
types, because user defined types (ie classes) are references, and built 
in types are not.  It looks to me like there is a huge change in 
thinking required between using built in types and user defined types.
Now, for most objects I think that references are correct and efficient. 
  However for the objects that are designed to look at act like built in 
types (ie, BigNum implementation), then they will NEVER behave exactly 
like built ins.

So I think the real question might be - how do we bridge the gap between 
user defined types and built in types?  This gap doesn't only show up in 
operators, but in passing values/references to functions.

...

I'll now solicit opinions and thoughts from the floor :)
I don't know enough about OO, or do enough pure software programming to 
know the right answer.

Brad
Apr 13 2005
next sibling parent reply xs0 <xs0 xs0.com> writes:
brad domain.invalid wrote:
 I think this needs a new thread.  Here is a snip of what I previously 
 posted...
 
 
 I got to thinking about what languages try to achieve with allowing 
 operator overloading, I think that they try to make user defined types 
 behave exactly as intrinsics.  This is especially important for a 
 language that allows templates, as your templates should work with built 
 in types and user defined types.  A while ago Derek ran across a problem 
   (thread title "opValue()") where his templates wouldn't work with 
 aggregates because "=" does a reference copy, when he infact wanted a 
 deep copy.
 I think that this is a similar problem - do programmers want their 
 operators to do a reference compare, or a deep compare?
 
 In thinking along these lines I realised that D (at the moment) does not 
 allow you to create user defined types that behave exactly as built in 
 types, because user defined types (ie classes) are references, and built 
 in types are not.  It looks to me like there is a huge change in 
 thinking required between using built in types and user defined types.
 Now, for most objects I think that references are correct and efficient. 
  However for the objects that are designed to look at act like built in 
 types (ie, BigNum implementation), then they will NEVER behave exactly 
 like built ins.
 
 So I think the real question might be - how do we bridge the gap between 
 user defined types and built in types?  This gap doesn't only show up in 
 operators, but in passing values/references to functions.
 
 ....
 
 I'll now solicit opinions and thoughts from the floor :)
 I don't know enough about OO, or do enough pure software programming to 
 know the right answer.
 
 Brad

Isn't a struct exactly what you want? It can have methods and operators and whatnot, yet has value semantics instead of reference semantics...
Apr 14 2005
parent reply Jan-Eric Duden <jeduden whisset.com> writes:
xs0 wrote:
 brad domain.invalid wrote:
 
 I think this needs a new thread.  Here is a snip of what I previously 
 posted...


 I got to thinking about what languages try to achieve with allowing 
 operator overloading, I think that they try to make user defined types 
 behave exactly as intrinsics.  This is especially important for a 
 language that allows templates, as your templates should work with 
 built in types and user defined types.  A while ago Derek ran across a 
 problem   (thread title "opValue()") where his templates wouldn't work 
 with aggregates because "=" does a reference copy, when he infact 
 wanted a deep copy.
 I think that this is a similar problem - do programmers want their 
 operators to do a reference compare, or a deep compare?

 In thinking along these lines I realised that D (at the moment) does 
 not allow you to create user defined types that behave exactly as 
 built in types, because user defined types (ie classes) are 
 references, and built in types are not.  It looks to me like there is 
 a huge change in thinking required between using built in types and 
 user defined types.
 Now, for most objects I think that references are correct and 
 efficient.  However for the objects that are designed to look at act 
 like built in types (ie, BigNum implementation), then they will NEVER 
 behave exactly like built ins.

 So I think the real question might be - how do we bridge the gap 
 between user defined types and built in types?  This gap doesn't only 
 show up in operators, but in passing values/references to functions.

 ....

 I'll now solicit opinions and thoughts from the floor :)
 I don't know enough about OO, or do enough pure software programming 
 to know the right answer.

 Brad

Isn't a struct exactly what you want? It can have methods and operators and whatnot, yet has value semantics instead of reference semantics...

Except that structs don't have constructors and destructors... which makes them second class objects.
Apr 14 2005
parent reply "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
"Jan-Eric Duden" <jeduden whisset.com> wrote in message
news:425E4730.5080908 whisset.com...
 xs0 wrote:
 brad domain.invalid wrote:

 I think this needs a new thread.  Here is a snip of what I previously
 posted...


 I got to thinking about what languages try to achieve with allowing
 operator overloading, I think that they try to make user defined types
 behave exactly as intrinsics.  This is especially important for a
 language that allows templates, as your templates should work with
 built in types and user defined types.  A while ago Derek ran across a
 problem   (thread title "opValue()") where his templates wouldn't work
 with aggregates because "=" does a reference copy, when he infact
 wanted a deep copy.
 I think that this is a similar problem - do programmers want their
 operators to do a reference compare, or a deep compare?

 In thinking along these lines I realised that D (at the moment) does
 not allow you to create user defined types that behave exactly as
 built in types, because user defined types (ie classes) are
 references, and built in types are not.  It looks to me like there is
 a huge change in thinking required between using built in types and
 user defined types.
 Now, for most objects I think that references are correct and
 efficient.  However for the objects that are designed to look at act
 like built in types (ie, BigNum implementation), then they will NEVER
 behave exactly like built ins.

 So I think the real question might be - how do we bridge the gap
 between user defined types and built in types?  This gap doesn't only
 show up in operators, but in passing values/references to functions.

 ....

 I'll now solicit opinions and thoughts from the floor :)
 I don't know enough about OO, or do enough pure software programming
 to know the right answer.

 Brad

Isn't a struct exactly what you want? It can have methods and operators and whatnot, yet has value semantics instead of reference semantics...

Except that structs don't have constructors and destructors... which makes them second class objects.

[----] I posted a solution to this problem in another thread, but it's such a long thread that most people probably skipped all or most of it. I know I only skimmed it myself, and missed the beginning of the thread entirely. Anyway, here it is again, since I think it should answer your question well (with additions and improvements)... For anything that the default opCmp() function (and therefore the "==" operator) currently compares the addresses rather than the contents, Change the opCmp() function to perform as follows (in this order, exiting when a return value has been established) when comparing (first_item == second_item)... If both items being compared are void, return 0 (equals). If first_item is void then return -1 (less than). If second_item is void then return 1 (greater than). Compare identities and return 0 (equals) if identical. Compare sizes and scan for the first difference within the smaller size number of bytes. If no differences are found, return the sign of the difference between the sizes. Otherwise return the sign of the difference at that location where the first difference was found. Furthermore, for any items that the "is" operator currently compares the contents by default, change it to instead compare the locations that they are stored at, if known. As nonsensical as that may seem, it would at least me consistant functionality of the operator, and there may even turn out to be emergent uses for it. Perhaps some simple override could allow programmers to change "is" back to comparing the contents for things like numeric litterals rather than their addresses, for those that choose to use it that way, or to support backward compatability... but I would consider that a minor issue. If the location of one or more of the items being compared is unknown (if this is even possible, but I don't see how it could be), then default to comparing the value or contents of the items. This way, all of the comparator operators would function predictably in a way that could be defined independant of what is being compared. The comparison would be efficient when possible, and would always be an accurate and predictable comparison that can be described without knowledge of what kinds of things are being compared. The least efficient case would be when the entire contents of the two items is searched for differences, and that would only happen if no differences were found before that and the two items were not one and the same. This could actually be accomplished rather quickly even if the items have very large contents, since the default comparison would be doing a very straight forward comparison independant of what kind of items are being compared. Optionally (this part may need some input) an exception could be raised is the contents of two items are found to be identical but no cast from one item to the other is known, since this would in some ways indicate that they may not actually be really "equal" afterall. There would no longer be ambiguous overlap between the "==" operator and the "is" operator, as each would have a clearly defined default function. In cases where the old functionality is wanted, or where a faster or otherwise different functionality is wanted, the operators could still be overriden, and any built-in overrides for certain kinds of items could be made where possible to conform to the same criteria of using "is" to compare addresses or locations for equality and the operators based on opCmp() to compare values or contents for equality or inequality. Perhaps "is" could also have a corrsponding "is<" and "is>" added to give more information... or maybe "precedes", "follows" and "isnt" but for now, I think what I have offered here can be converted into an actual solution to the current ambiguity and overlap of the "is" and "==" functionality. Okay... I'm tired, and I know I've made some mistakes in typing this... some of them potentially rather substantial.. for example, I am pretty sure I made a reference to an integer NAN value. If so... take that to mean something like "raise and exception" or what ever would make sense, because I'm just too tired to go back and edit it. I'm sending this as is, because I don't want to risk passing out at the keyboard from exhaustion, and hopefully it will still turn out to be helpful. It's been a rough day... but tomorrows another one. Oh, that didn't come out right at all. Hehe. Goodnight. TechnoZeus
Apr 14 2005
parent reply brad domain.invalid writes:
I'm afraid that only solves portions of the problem as I see it.  The 
main dividing line is that all builtin objects (and structs) are always 
value, but Objects are always by reference.
Which means
  - the assignment operator "=" can behave differently
  - function arguments can be either value or reference

And other things I am sure are broken as well.  This kind of thing 
mostly (I think) bites you when writing templates that can take both 
built-in types and user defined types.

Brad
Apr 14 2005
parent reply pragma <pragma_member pathlink.com> writes:
In article <d3mjsr$1obd$1 digitaldaemon.com>, brad domain.invalid says...
I'm afraid that only solves portions of the problem as I see it.  The 
main dividing line is that all builtin objects (and structs) are always 
value, but Objects are always by reference.
Which means
  - the assignment operator "=" can behave differently
  - function arguments can be either value or reference

And other things I am sure are broken as well.  This kind of thing 
mostly (I think) bites you when writing templates that can take both 
built-in types and user defined types.

Just a thought: would having ".dup" available universally help the assignment problem? int a,b; Integer c,d; a = b.dup; // duplicate the value of b c = d.dup; // duplicate the value of object d ('deep' copy) I would expect the signature "T opDup()" to be used in case of objects; providing it as a base member on Object would force the return type to "Object" (messy). As for function arguments, you could try using "inout" for all parameters to ensure that value types are given reference semantics. It's not the best workaround, but it gets the job done. - EricAnderton at yahoo
Apr 14 2005
parent reply "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
"pragma" <pragma_member pathlink.com> wrote in message
news:d3ml8g$1pgv$1 digitaldaemon.com...
 In article <d3mjsr$1obd$1 digitaldaemon.com>, brad domain.invalid says...
I'm afraid that only solves portions of the problem as I see it.  The
main dividing line is that all builtin objects (and structs) are always
value, but Objects are always by reference.
Which means
  - the assignment operator "=" can behave differently
  - function arguments can be either value or reference

And other things I am sure are broken as well.  This kind of thing
mostly (I think) bites you when writing templates that can take both
built-in types and user defined types.

Just a thought: would having ".dup" available universally help the assignment problem? int a,b; Integer c,d; a = b.dup; // duplicate the value of b c = d.dup; // duplicate the value of object d ('deep' copy) I would expect the signature "T opDup()" to be used in case of objects; providing it as a base member on Object would force the return type to "Object" (messy). As for function arguments, you could try using "inout" for all parameters to ensure that value types are given reference semantics. It's not the best workaround, but it gets the job done. - EricAnderton at yahoo

How about giving all items, including litterals, two properties as follows? .contents and .address such that .conents always means the internal value or contents of an item, and .address always means the location of that item in memory? For example, if X is an integer, then (X.address == 0) would compare the address of X with the integer value 0, while (X.contents == 0) would conpare the integer value of X with the integer value 0, and Y is an object, then (Y.address == 0) would compare the address in memory where the contents of Y are stored to the integer value 0, while (Y.contents == 0) would by default compare the bit pattern of the contents of Y with the bit pattern of the numeric litteral 0. This concept can actually be generallized to the point where one can code things like "if (12.address >= "hello".address){printf("the string was stored at a lower memory address than the number.");}" and there it allows instant removal of ambiguity no matter what kinds of things you're working with, as well as the ability to copy the contents of any object with a simple assignment such as "Y.contents = Z.contents" without wondering if you're going to end up making Y and Z point to the same object. Of course, I still think that the ambiguity should be removed from operators like "is" and "==" as much as reasonably possible, but a set of universal attributes like this would also help to facilitate that goal. TechnoZeus
Apr 14 2005
parent reply brad domain.invalid writes:
 How about giving all items, including litterals, two properties as follows?
 .contents
 and
 .address
 
 such that .conents always means the internal value or contents of an item, and
.address always means the location of that item in memory?
 
 For example, if X is an integer, then (X.address == 0) would compare the
address of X with the integer value 0, while (X.contents == 0) would conpare
the integer value of X with the integer value 0, and Y is an object, then
(Y.address == 0) would compare the address in memory where the contents of Y
are stored to the integer value 0, while (Y.contents == 0) would by default
compare the bit pattern of the contents of Y with the bit pattern of the
numeric litteral 0.
 
 This concept can actually be generallized to the point where one can code
things like "if (12.address >= "hello".address){printf("the string was stored
at a lower memory address than the number.");}" and there it allows instant
removal of ambiguity no matter what kinds of things you're working with, as
well as the ability to copy the contents of any object with a simple assignment
such as "Y.contents = Z.contents" without wondering if you're going to end up
making Y and Z point to the same object.
 
 
 Of course, I still think that the ambiguity should be removed from operators
like "is" and "==" as much as reasonably possible, but a set of universal
attributes like this would also help to facilitate that goal.
 
 TechnoZeus
 
 

nice to always have those properties so that in the cases you need to be sure you can be totally unambigious. I agree that "==" and "is" should be kept & as un-ambigious as possible. BTW - this is a problem that every language I can think of has - built in primitives are value, objects are generally reference/pointer. Maybe it would be interesting to make the builtins defaultly by reference? Brad
Apr 14 2005
parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
I haven't worked with it since it was still in it's beta development, so I'm
not sure if they retained it, but i know the C# language "had" this problem
worked out years ago.  Their solution was to allow all litterals to be treated
as objects when the programmer chose to do so, and to add in a set of
properties similar to what I have mentioned here, which were a part of every
object.  By allowing litterals to be boxed up as objects when an object based
property access was attempted, they had made it unnecessary to distinguish
between them other than for the sake of writing efficient code.

This is my point.  Make it consistant and easy to learn.  Those who have gotten
past the newbie phase can then concentrate on writing more efficient code while
those who haven't can concentrate on graduating to the next level.  This goes
not only for the programming language as a whole, but also for any part of it
that is still to any reasonable degree unfamilliar to a particular person, and
by extension, to the tools used by programmers to facilitate programming in the
language.

TZ

<brad domain.invalid> wrote in message news:d3ms27$1vb1$1 digitaldaemon.com...
 How about giving all items, including litterals, two properties as follows?
 .contents
 and
 .address

 such that .conents always means the internal value or contents of an item, and
.address always means the location of that item in memory?

 For example, if X is an integer, then (X.address == 0) would compare the
address of X with the integer value 0, while (X.contents == 0) would conpare
the integer value of X with the integer value 0, and Y is an object, then
(Y.address == 0) would compare the address in memory where the contents of Y
are stored to the integer value 0, while (Y.contents == 0) would by default
compare the bit pattern of the contents of Y with the bit pattern of the
numeric litteral 0.

 This concept can actually be generallized to the point where one can code
things like "if (12.address >= "hello".address){printf("the string was stored
at a lower memory address than the number.");}" and there it allows instant
removal of ambiguity no matter what kinds of things you're working with, as
well as the ability to copy the contents of any object with a simple assignment
such as "Y.contents = Z.contents" without wondering if you're going to end up
making Y and Z point to the same object.


 Of course, I still think that the ambiguity should be removed from operators
like "is" and "==" as much as reasonably possible, but a set of universal
attributes like this would also help to facilitate that goal.

 TechnoZeus

nice to always have those properties so that in the cases you need to be sure you can be totally unambigious. I agree that "==" and "is" should be kept & as un-ambigious as possible. BTW - this is a problem that every language I can think of has - built in primitives are value, objects are generally reference/pointer. Maybe it would be interesting to make the builtins defaultly by reference? Brad

Apr 14 2005
prev sibling next sibling parent "Ben Hinkle" <bhinkle mathworks.com> writes:
  However for the objects that are designed to look at act like built in
 types (ie, BigNum implementation), then they will NEVER behave exactly 
 like built ins.

I didn't have many problems mimicing a primitive numeric type when implementing the "big num" gmp wrapper. It's a class so you have to 'new' them, so that's one difference. Another is that toString is a member function instead of a top-level function. It would be nice to make it easier to write template code that works for both primitive, structs and classes when it makes sense, but I see that as a post-1.0 feature. Since the operator overloading returns new objects there isn't a problem of reference vs value. In general big nums work just like ints or other primitives. Check out http://home.comcast.net/~benhinkle/gmp-d/
Apr 14 2005
prev sibling next sibling parent reply Vladimir <kv11111 mail.ru> writes:
BTW, the simple workaround about general templates. Inside template one
could write
a=b+0;
instead of
a=b;
to emulate assignment by value.

But in my opinion having something like ":=" operator is much more
convenient.

-- 
          Vladimir
Apr 15 2005
next sibling parent reply "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
Ah, a Pascal fan.  Hehe.

Seriously though, yes... having an unambiguous assignment operator would be a
real plus, and since the ":=" operator is already established as such
elsewhere, it would be a good choice to add support for.  Use of the "="
operator could then be discouraged, in favor of the the ":=" operator, to help
avoid many common errors, and eventually perhaps the "=" operator would be
phased out to the point where it would make sense to flag a warning at compile
time if one is found.

Yes, I know what you mean about assignment by value... but I am even more
intregued by your mention of the ":=" assignment operator.  I'll give my
thoughts on that first, and then I'm going to ask for a slight clarification of
yours...

I'm not suggesting or condoning the change from "=" for assignment and "==" for
comparison to ":=" for assignment and "=" for comparison, as found in Pascal
and it's derivatives, but I would "strongly" recommend the simple addition of
":=" as an alternative assignment operator, and encouraging people to adapt
it's use, while continuing to use "==" as the equality comparison operator. 
This could be the best idea I've heard in years... Thanks Ben.

Okay, now... Ben... did you mean to have ":=" added as an "assign by value"
operator or just as an "assignment" operator?  Also, if you meant it as "assign
by value" (copy of the original data) then would you also have a specific
"assign by reference" operator in mind?... Furthermore, I'm curious what you
had in mind for the "=" operator.  Just leave it as is, or somethining else? 
Please, elaborate a bit.

TechnoZeus

TechnoZeus

"Vladimir" <kv11111 mail.ru> wrote in message
news:d3o2ho$al$1 digitaldaemon.com...
 BTW, the simple workaround about general templates. Inside template one
 could write
 a=b+0;
 instead of
 a=b;
 to emulate assignment by value.

 But in my opinion having something like ":=" operator is much more
 convenient.

 -- 
           Vladimir

Apr 15 2005
next sibling parent reply "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
Oops... my apologies, Vladimir.  I thought I was reading Ben's post.  Had
clicked on it in the list, and somehow got yours... didn't notice the
signature, until just as I clicked the "send" button.

Sorry about the confusion.  Anyway... Thanks for the great idea Vladimir. 
Please elaborate.

TechnoZeus

"TechnoZeus" <TechnoZeus PeoplePC.com> wrote in message
news:d3o93s$6n5$1 digitaldaemon.com...
 Ah, a Pascal fan.  Hehe.

 Seriously though, yes... having an unambiguous assignment operator would be a
real plus, and since the ":=" operator is already established as such
elsewhere, it would be a good choice to add support for.  Use of the "="
operator could then be discouraged, in favor of the the ":=" operator, to help
avoid many common errors, and eventually perhaps the "=" operator would be
phased out to the point where it would make sense to flag a warning at compile
time if one is found.

 Yes, I know what you mean about assignment by value... but I am even more
intregued by your mention of the ":=" assignment operator.  I'll give my
thoughts on that first, and then I'm going to ask for a slight clarification of
yours...

 I'm not suggesting or condoning the change from "=" for assignment and "=="
for comparison to ":=" for assignment and "=" for comparison, as found in
Pascal and it's derivatives, but I would "strongly" recommend the simple
addition of ":=" as an alternative assignment operator, and encouraging people
to adapt it's use, while continuing to use "==" as the equality comparison
operator.  This could be the best idea I've heard in years... Thanks Ben.

 Okay, now... Ben... did you mean to have ":=" added as an "assign by value"
operator or just as an "assignment" operator?  Also, if you meant it as "assign
by value" (copy of the original data) then would you also have a specific
"assign by reference" operator in mind?... Furthermore, I'm curious what you
had in mind for the "=" operator.  Just leave it as is, or somethining else? 
Please, elaborate a bit.

 TechnoZeus

 TechnoZeus

 "Vladimir" <kv11111 mail.ru> wrote in message
news:d3o2ho$al$1 digitaldaemon.com...
 BTW, the simple workaround about general templates. Inside template one
 could write
 a=b+0;
 instead of
 a=b;
 to emulate assignment by value.

 But in my opinion having something like ":=" operator is much more
 convenient.

 -- 
           Vladimir


Apr 15 2005
parent reply Vladimir <kv11111 mail.ru> writes:
TechnoZeus wrote:

 Oops... my apologies, Vladimir.  I thought I was reading Ben's post.  Had
 clicked on it in the list, and somehow got yours... didn't notice the
 signature, until just as I clicked the "send" button.
 
 Sorry about the confusion.  Anyway... Thanks for the great idea Vladimir. 
 Please elaborate.

Actually this is not my idea, look at the thread called opValue at the and of discussion. But I really like this idea and think it's very important. The only trouble is to convince Walter to allow this operator. For quick explanation, this it the extraction from that thread: ,--------------- Forwarded message (begin) Subject: Re: opValue() From: Regan Heath <regan netwin.co.nz> Date: Thu, 07 Apr 2005 05:34:52 +0400 Newsgroup: digitalmars.D On Thu, 07 Apr 2005 08:45:21 +1200, <brad domain.invalid> wrote:
 rter syntax:
  class T { T opShlAssign(Foo c) { /*...*/ return this; } }
  a<<=b; // almost like a=b, if you ask me
  I guess in 99.99999% cases, shifting an object to left with another  
 object doesn't make sense anyway, so the operator might as well get  
 another use..
   xs0

Argh! Surely not! I thought one of the philosophies of D was that operators should _always_ do what you expect. The <<= operator should always shift left & assign. Derek - am I right in saying that you want an assignment operator that doesn't create a new object, but instead alters an existing one? At the moment, when you deal with objects/references, the = operator always means "set this reference to this object". I don't think that it makes sense to overload this meaning, because you then end up with an operator that in some cases does "set this reference to this object" and in other cases "alter the internal data layout of object A, based on the values in object B" And then you end up with a whole lot of special rules to try and remember which assignment operator is applying. Overwriting the contents of an object when you really ment to assign to a new object could ruin your day if you hold multiple references to the object you are stomping on. I am in favour of having an operator that means "take object B, get some values out of it and setup object A accordingly"

And if they're the same type, it could be used for a "deep-copy"? I think we can combine this casting concern with the deep-copy concern, they seem closely related to me.
 Something like
 Foo a = new Foo ();
 Bar b = new Bar ();
 a <- b // which calls a.opConvert(b);

 I guess you could also end up with nasty
 a = (new Foo())<- b;

It seems 'correct' if 'ugly', done in 2 steps looks nicer and incurs no additional penalty (that I can see). a = new Foo(); a <- b; this operator is really a "copy RHS into LHS" operator, which implys that LHS must exists beforehand. Or using the "<-" operator could implicitly call new if the LHS is null... not sure how feasible that is.
 <- is probably not the operator to choose, probably hard to parse. Maybe  
 someone else can think of a good operator if this functionality is  
 required.

I agree, I think the main concern against this in Walters case was that implicit conversion when "=" is used can cause subtle behaviour and bugs. (correct me if I am wrong). So, if a new operator was used, eg. ":=" or something then this concern vanishes, as "=" does what it currently does: - shallow copy for arrays. - reference assignment for classes etc - deep copy for value types The new ":=" operator always means "copy RHS into LHS" AKA: - deep copy for arrays (provided items in array have deep-copy method defined) - deep copy for classes (provided class has deep-copy method defined) - same as "=" for value types. Thoughts? Regan `--------------- Forwarded message (end) -- Vladimir
Apr 15 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
To get some idea of context you're best to read the entire thread, tho  
it's a big one.. so, to make life easier I'm going to attempt to summarise  
it. (if anyone has corrections, please make them)

In essence Derek wanted to assign the value of an object with another. His  
initial idea was to use an overload of the assingment operator, as is done  
in C++.

D does not allow you to overload the assignment operator, I believe,  
because Walter dislikes the subtle behaviour this introduces, and in his  
experience subtle bugs can arise out of it.

Classes are references and assignment '=' does a reference assignment.  
Overloading '=' to do a value assignment for a class would change this  
behaviour.

So, how to solve Dereks requirement of a value assignment for a reference  
type.

It occured to me that this was identical to a "deep copy" where the object  
being assigned was the same type as the value being assigned.

So, "to kill 2 birds with one stone" (AKA solve both problems at once) I  
figured a value assignment operator was required. I remember someone  
talking about ":=" and it's use in other languages, tho I've never used  
them, so I suggested it.

It also occured to me that we have "==" and "is" for value and identity  
comparisons (albeit with exceptions - IMO sensible ones) and it therefore  
makes sense to have ":=" and "=" for value and identity assignments  
(interestingly with all the same exceptions as "==" and "is" operate  
under).

My take on "==" and "is" (for reference):

1. "==" does value comparison.
2. "is" does identity comparison.

Exception to 1, a reference type with no defined method of comparison is  
compared using identity. If identity is equal, value will be equal. If  
identity is not equal then given no way to compare value one must assume  
inequality or throw an exception. (D assumes inequality, an exception can  
be thrown by coding it manually)

Exception to 2, a value type. No 2 values types can compare equal in  
identity. Technically this could be an error? However, D does a value  
comparison. A lint program could catch and error on this. I see little  
point and quite like the way "if (a is 5)" (where a is an 'int' or  
similar) reads.

How these exceptions apply to "=" and ":=":

1. ":=" does value assignment
2. "="  does identity assignment

Exception to 1, a reference type with no defined method of assignment.  
Best behaviour here would be an error IMO.

Exception to 2, a value type. You cannot assign identity to a value type,  
so you assign value (current D behaviour).

So, as you can see the exceptions are parallel, the behvaiour of "=" need  
not change, all that is added is ":=" and opAssign overloads for reference  
types.

Regan

On Fri, 15 Apr 2005 21:00:25 +0400, Vladimir <kv11111 mail.ru> wrote:
 TechnoZeus wrote:

 Oops... my apologies, Vladimir.  I thought I was reading Ben's post.   
 Had
 clicked on it in the list, and somehow got yours... didn't notice the
 signature, until just as I clicked the "send" button.

 Sorry about the confusion.  Anyway... Thanks for the great idea  
 Vladimir.
 Please elaborate.

Actually this is not my idea, look at the thread called opValue at the and of discussion. But I really like this idea and think it's very important. The only trouble is to convince Walter to allow this operator. For quick explanation, this it the extraction from that thread: ,--------------- Forwarded message (begin) Subject: Re: opValue() From: Regan Heath <regan netwin.co.nz> Date: Thu, 07 Apr 2005 05:34:52 +0400 Newsgroup: digitalmars.D On Thu, 07 Apr 2005 08:45:21 +1200, <brad domain.invalid> wrote: > rter syntax: >> class T { T opShlAssign(Foo c) { /*...*/ return this; } } >> a<<=b; // almost like a=b, if you ask me >> I guess in 99.99999% cases, shifting an object to left with another >> object doesn't make sense anyway, so the operator might as well get >> another use.. >> xs0 > > Argh! Surely not! I thought one of the philosophies of D was that > operators should _always_ do what you expect. The <<= operator should > always shift left & assign. > > Derek - am I right in saying that you want an assignment operator that > doesn't create a new object, but instead alters an existing one? At the > moment, when you deal with objects/references, the = operator always > means "set this reference to this object". I don't think that it makes > sense to overload this meaning, because you then end up with an operator > that in some cases does > "set this reference to this object" and in other cases > "alter the internal data layout of object A, based on the values in > object B" > And then you end up with a whole lot of special rules to try and > remember which assignment operator is applying. Overwriting the > contents of an object when you really ment to assign to a new object > could ruin your day if you hold multiple references to the object you > are stomping on. > > I am in favour of having an operator that means "take object B, get some > values out of it and setup object A accordingly" And if they're the same type, it could be used for a "deep-copy"? I think we can combine this casting concern with the deep-copy concern, they seem closely related to me.
 Something like

> Bar b = new Bar (); > a <- b // which calls a.opConvert(b); > > I guess you could also end up with nasty > a = (new Foo())<- b; It seems 'correct' if 'ugly', done in 2 steps looks nicer and incurs no additional penalty (that I can see). a = new Foo(); a <- b; this operator is really a "copy RHS into LHS" operator, which implys that LHS must exists beforehand. Or using the "<-" operator could implicitly call new if the LHS is null... not sure how feasible that is.
 <- is probably not the operator to choose, probably hard to parse.  

> someone else can think of a good operator if this functionality is > required. I agree, I think the main concern against this in Walters case was that implicit conversion when "=" is used can cause subtle behaviour and bugs. (correct me if I am wrong). So, if a new operator was used, eg. ":=" or something then this concern vanishes, as "=" does what it currently does: - shallow copy for arrays. - reference assignment for classes etc - deep copy for value types The new ":=" operator always means "copy RHS into LHS" AKA: - deep copy for arrays (provided items in array have deep-copy method defined) - deep copy for classes (provided class has deep-copy method defined) - same as "=" for value types. Thoughts? Regan `--------------- Forwarded message (end)

Apr 15 2005
next sibling parent reply Vladimir <kv11111 mail.ru> writes:
Thanks a lot for good summary.

Regan Heath wrote:
 My take on "==" and "is" (for reference):
 
 1. "==" does value comparison.
 2. "is" does identity comparison.
 
 Exception to 1, a reference type with no defined method of comparison is
 compared using identity. If identity is equal, value will be equal. If
 identity is not equal then given no way to compare value one must assume
 inequality or throw an exception. (D assumes inequality, an exception can
 be thrown by coding it manually)
 
 Exception to 2, a value type. No 2 values types can compare equal in
 identity. Technically this could be an error? However, D does a value
 comparison. A lint program could catch and error on this. I see little
 point and quite like the way "if (a is 5)" (where a is an 'int' or
 similar) reads.

objects, the second will be changed too. But know I understand that this is wrong for built-in types. This could be another problem for general template programming.
 How these exceptions apply to "=" and ":=":
 
 1. ":=" does value assignment
 2. "="  does identity assignment
 
 Exception to 1, a reference type with no defined method of assignment.
 Best behaviour here would be an error IMO.
 
 Exception to 2, a value type. You cannot assign identity to a value type,
 so you assign value (current D behaviour).
 
 So, as you can see the exceptions are parallel, the behvaiour of "=" need
 not change, all that is added is ":=" and opAssign overloads for reference
 types.
 
 Regan
 

-- Vladimir
Apr 16 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Sat, 16 Apr 2005 12:21:28 +0400, Vladimir <kv11111 mail.ru> wrote:
 Thanks a lot for good summary.

 Regan Heath wrote:
 My take on "==" and "is" (for reference):

 1. "==" does value comparison.
 2. "is" does identity comparison.

 Exception to 1, a reference type with no defined method of comparison is
 compared using identity. If identity is equal, value will be equal. If
 identity is not equal then given no way to compare value one must assume
 inequality or throw an exception. (D assumes inequality, an exception  
 can
 be thrown by coding it manually)

 Exception to 2, a value type. No 2 values types can compare equal in
 identity. Technically this could be an error? However, D does a value
 comparison. A lint program could catch and error on this. I see little
 point and quite like the way "if (a is 5)" (where a is an 'int' or
 similar) reads.


 I thought that equality by identity means that if I change one of two  
 equal objects, the second will be changed too.

If they're objects (AKA references, AKA reference types), and you change the "value", yes.
 But know I understand that this is
 wrong for built-in types.

But not for all built in types. "char[]" is a built in tpye, an array. It is a "reference type". "int" is a built in type. It is a "value type".
 This could be another problem for general
 template programming.

Agreed. I like having both value and reference types, they have thier uses. Having the ability to restrict templates, and/or having operators/methods with identical behaviour for both types of types solves the template issues. I believe having a ":=" value assignment operator helps. Regan
Apr 16 2005
parent reply "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
Nice summary.  Thanks.

Two points I would like to bring up....

First, is that value types do have an identity.  Even a litteral has an
identity, because it has to be stored "somewhere" to be used. Therefore, it may
be "possible" but undesireable to allow identity assignemnts to value types in
general.  In cases where it is desireable, pointers would suffice.  Not an
argument for or against anything you said... just a detail that I thought
should be mentioned.

Second, is that while I think adding ":=" as a value assignemt operator would
be a great idea, I also think that making "=" into something that it's not
would be a very bad idea.  If there is to be a "reference assignment" operator,
I think it should be something that is not currently in use.

In other words, as messy as it is, I would say leave the "=" operator have it's
current quirks, for backward compatibility if nothing else, but add ":=" for
value assignments, and add an identity assignment operator so that explicit
identity assignments or would be possible without having to resort to using
value assignments on pointer types and without having to use the "=" operator
if the programmer chooses to avoid it.  This way, perhaps a compiler switch
could even be added that would warn on the use of the "=" operator, so that
people who have found it to be involved in the production of too many bugs
could phase it out if they so choose.

Also, I would personally recommend that the following two default members be
supported on everything that is capable of supporting them:  ".value" to
explicitly access or assign the item's value, and ".identity" to explicitly
access or assign the item's identity.

Most important though of all that's been mentioned in this thread, in my
opinion, would be the addition of a ":=" value assigment operator.  (Perhaps
=:= could be added also as an explicit value comparison operator.  Also, >:=
and <:= and so on, as well as the natural extension to +:= and -:= and so on
for explicit "modify and assign value" operators.  Just a thought.)

TZ

"Regan Heath" <regan netwin.co.nz> wrote in message
news:opspblnau423k2f5 nrage.netwin.co.nz...
 On Sat, 16 Apr 2005 12:21:28 +0400, Vladimir <kv11111 mail.ru> wrote:
 Thanks a lot for good summary.

 Regan Heath wrote:
 My take on "==" and "is" (for reference):

 1. "==" does value comparison.
 2. "is" does identity comparison.

 Exception to 1, a reference type with no defined method of comparison is
 compared using identity. If identity is equal, value will be equal. If
 identity is not equal then given no way to compare value one must assume
 inequality or throw an exception. (D assumes inequality, an exception
 can
 be thrown by coding it manually)

 Exception to 2, a value type. No 2 values types can compare equal in
 identity. Technically this could be an error? However, D does a value
 comparison. A lint program could catch and error on this. I see little
 point and quite like the way "if (a is 5)" (where a is an 'int' or
 similar) reads.


 I thought that equality by identity means that if I change one of two
 equal objects, the second will be changed too.

If they're objects (AKA references, AKA reference types), and you change the "value", yes.
 But know I understand that this is
 wrong for built-in types.

But not for all built in types. "char[]" is a built in tpye, an array. It is a "reference type". "int" is a built in type. It is a "value type".
 This could be another problem for general
 template programming.

Agreed. I like having both value and reference types, they have thier uses. Having the ability to restrict templates, and/or having operators/methods with identical behaviour for both types of types solves the template issues. I believe having a ":=" value assignment operator helps. Regan

Apr 20 2005
next sibling parent reply brad beveridge <brad nowhere.com> writes:
TechnoZeus wrote:
 Nice summary.  Thanks.
 
 Two points I would like to bring up....
 
 First, is that value types do have an identity.  Even a litteral has an
identity, because it has to be stored "somewhere" to be used. Therefore, it may
be "possible" but undesireable to allow identity assignemnts to value types in
general.  In cases where it is desireable, pointers would suffice.  Not an
argument for or against anything you said... just a detail that I thought
should be mentioned.
 
 Second, is that while I think adding ":=" as a value assignemt operator would
be a great idea, I also think that making "=" into something that it's not
would be a very bad idea.  If there is to be a "reference assignment" operator,
I think it should be something that is not currently in use.
 
 In other words, as messy as it is, I would say leave the "=" operator have
it's current quirks, for backward compatibility if nothing else, but add ":="
for value assignments, and add an identity assignment operator so that explicit
identity assignments or would be possible without having to resort to using
value assignments on pointer types and without having to use the "=" operator
if the programmer chooses to avoid it.  This way, perhaps a compiler switch
could even be added that would warn on the use of the "=" operator, so that
people who have found it to be involved in the production of too many bugs
could phase it out if they so choose.
 
 Also, I would personally recommend that the following two default members be
supported on everything that is capable of supporting them:  ".value" to
explicitly access or assign the item's value, and ".identity" to explicitly
access or assign the item's identity.
 
 Most important though of all that's been mentioned in this thread, in my
opinion, would be the addition of a ":=" value assigment operator.  (Perhaps
=:= could be added also as an explicit value comparison operator.  Also, >:=
and <:= and so on, as well as the natural extension to +:= and -:= and so on
for explicit "modify and assign value" operators.  Just a thought.)
 
 TZ

special "identity assignment" operator just yet - but I am fully infavour of the ".value" and ".address" properties for all types. If people find they are typing "x.address = y.address" on a regular basis, then we would have a case for an address assignment operator. Walter - what do you think of this discussion? Cheers Brad
Apr 20 2005
parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
Yes, I agree fully.

Walter?  Could we please have a ":=" value assignment opperator, that assigns
values by default and never assigns an address unless that address is actually
the value of the item (such as the value of a pointer, for example)?

TZ

"brad beveridge" <brad nowhere.com> wrote in message
news:d458ge$2p8p$1 digitaldaemon.com...
 TechnoZeus wrote:
 Nice summary.  Thanks.

 Two points I would like to bring up....

 First, is that value types do have an identity.  Even a litteral has an
identity, because it has to be stored "somewhere" to be used. Therefore, it may
be "possible" but undesireable to allow identity assignemnts to value types in
general.  In cases where it is desireable, pointers would suffice.  Not an
argument for or against anything you said... just a detail that I thought
should be mentioned.

 Second, is that while I think adding ":=" as a value assignemt operator would
be a great idea, I also think that making "=" into something that it's not
would be a very bad idea.  If there is to be a "reference assignment" operator,
I think it should be something that is not currently in use.

 In other words, as messy as it is, I would say leave the "=" operator have
it's current quirks, for backward compatibility if nothing else, but add ":="
for value assignments, and add an identity assignment operator so that explicit
identity assignments or would be possible without having to resort to using
value assignments on pointer types and without having to use the "=" operator
if the programmer chooses to avoid it.  This way, perhaps a compiler switch
could even be added that would warn on the use of the "=" operator, so that
people who have found it to be involved in the production of too many bugs
could phase it out if they so choose.

 Also, I would personally recommend that the following two default members be
supported on everything that is capable of supporting them:  ".value" to
explicitly access or assign the item's value, and ".identity" to explicitly
access or assign the item's identity.

 Most important though of all that's been mentioned in this thread, in my
opinion, would be the addition of a ":=" value assigment operator.  (Perhaps
=:= could be added also as an explicit value comparison operator.  Also, >:=
and <:= and so on, as well as the natural extension to +:= and -:= and so on
for explicit "modify and assign value" operators.  Just a thought.)

 TZ

special "identity assignment" operator just yet - but I am fully infavour of the ".value" and ".address" properties for all types. If people find they are typing "x.address = y.address" on a regular basis, then we would have a case for an address assignment operator. Walter - what do you think of this discussion? Cheers Brad

Apr 20 2005
prev sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Wed, 20 Apr 2005 03:20:01 -0500, TechnoZeus <TechnoZeus PeoplePC.com>  
wrote:
 Nice summary.  Thanks.

 Two points I would like to bring up....

 First, is that value types do have an identity.  Even a litteral has an  
 identity, because it has to be stored "somewhere" to be used.

Agreed.
 Therefore, it may be "possible" but undesireable to allow identity  
 assignemnts to value types in general.

Something like: int a,b; &a = &b; This would effectively ignore the memory 'a' occupied and make 'a' and alias of 'b'.
 In cases where it is desireable, pointers would suffice.

Pointers are a piece of memory whose value is the address of a piece of memory. (I'm sure you know this.. I'm just leading in..) They don't really facilitate identity assignment of value types, rather, they themselves have a fixed identity (the addres in which they are stored) and their value is the identity of something else (or themselves). You can assign to them another identiy, but this doesn't effect their identity, the identity of the value to which they are assigned or were previously assigned.
 Not an argument for or against anything you said... just a detail that I  
 thought should be mentioned.

Splitting hairs is fun, often I find it asks you to look at something in a different light, usually increasing understanding of the subject overall.
 Second, is that while I think adding ":=" as a value assignemt operator  
 would be a great idea, I also think that making "=" into something that  
 it's not would be a very bad idea.  If there is to be a "reference  
 assignment" operator, I think it should be something that is not  
 currently in use.

"=" is currently a reference assignment operator (for reference types) and a value assignment operator (for value types). I wasn't suggesting that it change in any way. I can see, re-reading my post, how by labelling it a "reference assignment" I might have given an impression of change, but note the "exception" I spoke of and my conclusion: <quote> 2. "=" does identity assignment ... Exception to 2, a value type. You cannot assign identity to a value type, so you assign value (current D behaviour). So, as you can see the exceptions are parallel, the behvaiour of "=" need not change, all that is added is ":=" and opAssign overloads for reference types. </quote> In short, leave it the same as it is currently.
 In other words, as messy as it is, I would say leave the "=" operator  
 have it's current quirks, for backward compatibility if nothing else,

Yes.
 but add ":=" for value assignments,

Yes.
 and add an identity assignment operator so that explicit identity  
 assignments or would be possible without having to resort to using value  
 assignments on pointer types and without having to use the "=" operator  
 if the programmer chooses to avoid it.

I don't see a point in this. All you're really doing is creating another name for an existing type, just like passing it into a function with "inout" does. Currently you can achieve this by: - passing it into a function using 'inout'. - using "alias". Personally I have never had the need to alias an existing type in this way. However, thinking about it... If _anything_ I would suggest adding a referece type specifier, eg. int a; int& b; //reference type, like C++ reference parameters to functions. b = a; //reference assignment, as 'b' is a reference type; b = 5; //assigns 'a' to 5 assert(a == b); this would have the syntax of a value type, but be a reference to some other value type elsewhere. Note, the "=" operator does not change in any way and no explicit identity assignment operator is required. However, if these were added then "is" would need to change to handle "if (b is a)" i.e. is "b" a reference to "a", luckily the LHS is a reference type, so this might not be too hard to manage.
 Also, I would personally recommend that the following two default  
 members be supported on everything that is capable of supporting them:   
 ".value" to explicitly access or assign the item's value, and  
 ".identity" to explicitly access or assign the item's identity.

Assuming: - there is little need to assign identity for value types. - we have methods to do so, inout, alias. or we add a reference type for value types. then I see no point in this.
 Most important though of all that's been mentioned in this thread, in my  
 opinion, would be the addition of a ":=" value assigment operator.

Agreed.
 (Perhaps =:= could be added also as an explicit value comparison  
 operator.  Also, >:= and <:= and so on, as well as the natural extension  
 to +:= and -:= and so on for explicit "modify and assign value"  
 operators.  Just a thought.)

I like how the current operators function. They already cover all the bases defaulting to the most sensible operation. Regan
 "Regan Heath" <regan netwin.co.nz> wrote in message  
 news:opspblnau423k2f5 nrage.netwin.co.nz...
 On Sat, 16 Apr 2005 12:21:28 +0400, Vladimir <kv11111 mail.ru> wrote:
 Thanks a lot for good summary.

 Regan Heath wrote:
 My take on "==" and "is" (for reference):

 1. "==" does value comparison.
 2. "is" does identity comparison.

 Exception to 1, a reference type with no defined method of  


 compared using identity. If identity is equal, value will be equal.  


 identity is not equal then given no way to compare value one must  


 inequality or throw an exception. (D assumes inequality, an exception
 can
 be thrown by coding it manually)

 Exception to 2, a value type. No 2 values types can compare equal in
 identity. Technically this could be an error? However, D does a value
 comparison. A lint program could catch and error on this. I see  


 point and quite like the way "if (a is 5)" (where a is an 'int' or
 similar) reads.


 I thought that equality by identity means that if I change one of two
 equal objects, the second will be changed too.

If they're objects (AKA references, AKA reference types), and you change the "value", yes.
 But know I understand that this is
 wrong for built-in types.

But not for all built in types. "char[]" is a built in tpye, an array. It is a "reference type". "int" is a built in type. It is a "value type".
 This could be another problem for general
 template programming.

Agreed. I like having both value and reference types, they have thier uses. Having the ability to restrict templates, and/or having operators/methods with identical behaviour for both types of types solves the template issues. I believe having a ":=" value assignment operator helps. Regan


Apr 20 2005
next sibling parent reply Vladimir <kv11111 mail.ru> writes:
Regan Heath wrote:
 
 Assuming:
   - there is little need to assign identity for value types.

that '=' is identity assignment operator decided to implement some features relying on it, for example symmetric matrixes: for(i=0; i<10; i++) for(j=0; j<i; j++) matrix[j][i] = matrix[i][j]; ... matrix[1][2] = 10; If matrix is array of objects then we have matrix[1][2] = matrix[2][1] = 10, but it differs for built-in types. May be just disallow of using '=' for built-in types and allow only ':=', but for classes allow both of them ?
   - we have methods to do so, inout, alias.
     or we add a reference type for value types.

-- Vladimir
Apr 20 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Wed, 20 Apr 2005 17:21:59 +0400, Vladimir <kv11111 mail.ru> wrote:
 Regan Heath wrote:
 Assuming:
   - there is little need to assign identity for value types.

reading that '=' is identity assignment operator decided to implement some features relying on it, for example symmetric matrixes: for(i=0; i<10; i++) for(j=0; j<i; j++) matrix[j][i] = matrix[i][j]; ... matrix[1][2] = 10; If matrix is array of objects then we have matrix[1][2] = matrix[2][1] = 10, but it differs for built-in types.

True.
 May be just disallow of using '=' for built-in types and allow only ':=',
 but for classes allow both of them ?

If your intention is to assign "value" then you'd use ":=" not "=".
   - we have methods to do so, inout, alias.
     or we add a reference type for value types.


True. "inout" is the only runtime one. I'm still not convinced of the need to alias value types. However, assuming there is a need I would use a "basic reference type" i.e. "int a; int& b;" (see my last post for more details). Regan Regan
Apr 20 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Thu, 21 Apr 2005 09:36:30 +1200, Regan Heath <regan netwin.co.nz> wrote:
 On Wed, 20 Apr 2005 17:21:59 +0400, Vladimir <kv11111 mail.ru> wrote:
 Regan Heath wrote:
 Assuming:
   - there is little need to assign identity for value types.

reading that '=' is identity assignment operator


If they read this, it was poorly written because it's untrue. (I did try to qualify my statement when I said that, didn't I?)
 decided to implement some features
 relying on it, for example symmetric matrixes:

 for(i=0; i<10; i++)
         for(j=0; j<i; j++)
                 matrix[j][i] = matrix[i][j];
 ...
 matrix[1][2] = 10;

 If matrix is array of objects then we have matrix[1][2] = matrix[2][1]  
 = 10, but it differs for built-in types.

True.
 May be just disallow of using '=' for built-in types and allow only  
 ':=',
 but for classes allow both of them ?

If your intention is to assign "value" then you'd use ":=" not "=".

Or, flipside, if your intention was to assign "identity".. If your matrix contained value types it would not work, so... 1. Currently you could use "int*" to achieve what you want. 2. Or, adding a "basic reference type" i.e. "int& a" would allow you to have a matrix of them, and get identity assignment. 3. Of course, adding an identity assignment operator and allowing identity assignment for value types would also work (provided you used that operator). As to what method is best.. I'm not sure. #2 and #3 are a lot of work (I expect). #3 is alien (at least to me, and probably other C/C++/Java programmers). Leaving #1, which is essentially not using a value type where a reference type is required. Regan
Apr 20 2005
next sibling parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
Not sure whether this would be advantageous or not,
but perhaps the "=" operator could be deprecated where it functions as a value
assignment operator, so that it could be phased out in that capacity.

Okay... separate thread on a thought about deprecation, comming up.  :)

TZ


"Regan Heath" <regan netwin.co.nz> wrote in message
news:opspjwazw323k2f5 nrage.netwin.co.nz...
 On Thu, 21 Apr 2005 09:36:30 +1200, Regan Heath <regan netwin.co.nz> wrote:
 On Wed, 20 Apr 2005 17:21:59 +0400, Vladimir <kv11111 mail.ru> wrote:
 Regan Heath wrote:
 Assuming:
   - there is little need to assign identity for value types.

reading that '=' is identity assignment operator


If they read this, it was poorly written because it's untrue. (I did try to qualify my statement when I said that, didn't I?)
 decided to implement some features
 relying on it, for example symmetric matrixes:

 for(i=0; i<10; i++)
         for(j=0; j<i; j++)
                 matrix[j][i] = matrix[i][j];
 ...
 matrix[1][2] = 10;

 If matrix is array of objects then we have matrix[1][2] = matrix[2][1]
 = 10, but it differs for built-in types.

True.
 May be just disallow of using '=' for built-in types and allow only
 ':=',
 but for classes allow both of them ?

If your intention is to assign "value" then you'd use ":=" not "=".

Or, flipside, if your intention was to assign "identity".. If your matrix contained value types it would not work, so... 1. Currently you could use "int*" to achieve what you want. 2. Or, adding a "basic reference type" i.e. "int& a" would allow you to have a matrix of them, and get identity assignment. 3. Of course, adding an identity assignment operator and allowing identity assignment for value types would also work (provided you used that operator). As to what method is best.. I'm not sure. #2 and #3 are a lot of work (I expect). #3 is alien (at least to me, and probably other C/C++/Java programmers). Leaving #1, which is essentially not using a value type where a reference type is required. Regan

Apr 20 2005
prev sibling parent reply Vladimir <kv11111 mail.ru> writes:
Regan Heath wrote:

 On Thu, 21 Apr 2005 09:36:30 +1200, Regan Heath <regan netwin.co.nz>
 wrote:
 On Wed, 20 Apr 2005 17:21:59 +0400, Vladimir <kv11111 mail.ru> wrote:
 Regan Heath wrote:
 Assuming:
   - there is little need to assign identity for value types.

reading that '=' is identity assignment operator


If they read this, it was poorly written because it's untrue. (I did try to qualify my statement when I said that, didn't I?)
 decided to implement some features
 relying on it, for example symmetric matrixes:

 for(i=0; i<10; i++)
         for(j=0; j<i; j++)
                 matrix[j][i] = matrix[i][j];
 ...
 matrix[1][2] = 10;

 If matrix is array of objects then we have matrix[1][2] = matrix[2][1]
 = 10, but it differs for built-in types.

True.
 May be just disallow of using '=' for built-in types and allow only
 ':=',
 but for classes allow both of them ?

If your intention is to assign "value" then you'd use ":=" not "=".

Or, flipside, if your intention was to assign "identity".. If your matrix contained value types it would not work, so... 1. Currently you could use "int*" to achieve what you want.

(and I do not understand why we need both references and pointers for classes).
 2. Or, adding a "basic reference type" i.e. "int& a" would allow you to
 have a matrix of them, and get identity assignment.

for classes C& makes no sense so we can make C& be the same type as C.
 3. Of course, adding an identity assignment operator and allowing identity
 assignment for value types would also work (provided you used that
 operator).

run-time symbol tables, they assigns address to variable at compile time, and it can't be changed at run-time.
 As to what method is best.. I'm not sure. #2 and #3 are a lot of work (I
 expect). #3 is alien (at least to me, and probably other C/C++/Java
 programmers). Leaving #1, which is essentially not using a value type
 where a reference type is required.
 
 Regan

In C++ there were value-type and reference-type for any class or built-in type. In D we have only reference-type for classes and only value-type for anything else (pointers are something else). Adding := operator will smooth this asymmetry, but not remove it totally. I can see at least these remaining problems: 1. absent reference-type for non-classes (discussed above). 2. reference-type variable are always initialized to null, while value-type can't be null 3. different behavior of 'is' operator for value-type and reference-type. To illustrate some of this: /* Class for calculation some difficult function and caching result */ /* Suppose reverse function is easy to calculate */ class SomeFunction(T) { T _cached_val; T calculate(T input) { /* if T is class we have seg-v here at first invocation * because _cached_val is null */ if(input == calculate_reverse(_cached_val)) /* if T is class then by returning _cached_val we allow caller * to change it and hurt our presious cache */ return _cached_val; /* if we have := we can write * { R t := _chached_val; return t; } * but it's ugly and slow if R is big value-type struct */ /* if T is value-type it won't compile */ if( _cached_val is null ) {} /* here we obviously need := */ _cached_for = input; /* here we change caller's variable if T is class, * and := can't solve out problem */ input += 10; ... /* again we have problem here */ return _cached_val; } T calculate_reverse(T input) { ... } } -- Vladimir
Apr 21 2005
next sibling parent reply brad beveridge <brad nowhere.com> writes:
Vladimir wrote:
<snip>

 To illustrate some of this:

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? Brad
Apr 21 2005
next sibling parent reply "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
Define "better" in that context.

True, it wouldn't solve "all" problems, but then again, nothing ever will.

There are obviously advantages to adding a := operator for value assignments,
and I have yet to hear a down side to it.

TZ

"brad beveridge" <brad nowhere.com> wrote in message
news:d47ro7$2lem$1 digitaldaemon.com...
 Vladimir wrote:
 <snip>

 To illustrate some of this:

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? Brad

Apr 21 2005
parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
"TechnoZeus" <TechnoZeus PeoplePC.com> wrote in message 
news:d48b73$2m6$1 digitaldaemon.com...
 Define "better" in that context.

 True, it wouldn't solve "all" problems, but then again, nothing ever will.

 There are obviously advantages to adding a := operator for value 
 assignments, and I have yet to hear a down side to it.

 TZ

http://www.digitalmars.com/d/faq.html#assignmentoverloading
Apr 21 2005
parent reply "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
"Ben Hinkle" <bhinkle mathworks.com> wrote in message
news:d48chi$48n$1 digitaldaemon.com...
 "TechnoZeus" <TechnoZeus PeoplePC.com> wrote in message
 news:d48b73$2m6$1 digitaldaemon.com...
 Define "better" in that context.

 True, it wouldn't solve "all" problems, but then again, nothing ever will.

 There are obviously advantages to adding a := operator for value
 assignments, and I have yet to hear a down side to it.

 TZ

http://www.digitalmars.com/d/faq.html#assignmentoverloading

Hi Ben. Why the link to information about assignment overloading? TZ
Apr 21 2005
parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
 There are obviously advantages to adding a := operator for value
 assignments, and I have yet to hear a down side to it.

http://www.digitalmars.com/d/faq.html#assignmentoverloading

Why the link to information about assignment overloading?

That's what this discussion on := and opAssign are about. Walter has already thought about overloading assignment and it has come up before on the newsgroup (I actually found that link during a quick search of the archives).
Apr 21 2005
next sibling parent Vladimir <kv11111 mail.ru> writes:
Ben Hinkle wrote:

 There are obviously advantages to adding a := operator for value
 assignments, and I have yet to hear a down side to it.

http://www.digitalmars.com/d/faq.html#assignmentoverloading

Why the link to information about assignment overloading?

That's what this discussion on := and opAssign are about. Walter has already thought about overloading assignment and it has come up before on the newsgroup (I actually found that link during a quick search of the archives).

writing general templates that must work with classes as well as with fundamental types. Addition of := operator may require making it overloadable because of external resource allocation (not only memory allocation but also opened files, DB connections and so on). Allowing := overloading also will solve casting problem (for example ability to write BigInt class in such way that code { BigInt i; i:=100; } can be compiled), but this is just side-effect. But again, even adding this operator will not solve the whole problem with general templates. -- Vladimir
Apr 21 2005
prev sibling parent reply "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
It's a big thread... that might have been in it somewhere.
This branch of it deals with adding ":=" as a separate operator in addition to
the "=" operator,
and having ":=" act as a value assignment operator such that...
a := b;
anways results in (a == b) being true, but never makes (a is b) become true.

Not related to overloading the "=" operator.

TZ

"Ben Hinkle" <bhinkle mathworks.com> wrote in message
news:d48dc2$54g$1 digitaldaemon.com...
 There are obviously advantages to adding a := operator for value
 assignments, and I have yet to hear a down side to it.

http://www.digitalmars.com/d/faq.html#assignmentoverloading

Why the link to information about assignment overloading?

That's what this discussion on := and opAssign are about. Walter has already thought about overloading assignment and it has come up before on the newsgroup (I actually found that link during a quick search of the archives).

Apr 21 2005
parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
"TechnoZeus" <TechnoZeus PeoplePC.com> wrote in message 
news:d48iic$9se$1 digitaldaemon.com...
 It's a big thread... that might have been in it somewhere.
 This branch of it deals with adding ":=" as a separate operator in 
 addition to the "=" operator,
 and having ":=" act as a value assignment operator such that...
 a := b;
 anways results in (a == b) being true, but never makes (a is b) become 
 true.

 Not related to overloading the "=" operator.

 TZ

hehe. Sorry but it sounds funny to say an operator called := with overload opAssign is not related to overloading assignment. I would bet no matter what the symbol is and the overload name Walter's objections would still apply. ps - I should have asked you to do my taxes :-)
Apr 21 2005
next sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Thu, 21 Apr 2005 12:44:35 -0400, Ben Hinkle <ben.hinkle gmail.com>  
wrote:
 "TechnoZeus" <TechnoZeus PeoplePC.com> wrote in message
 news:d48iic$9se$1 digitaldaemon.com...
 It's a big thread... that might have been in it somewhere.
 This branch of it deals with adding ":=" as a separate operator in
 addition to the "=" operator,
 and having ":=" act as a value assignment operator such that...
 a := b;
 anways results in (a == b) being true, but never makes (a is b) become
 true.

 Not related to overloading the "=" operator.

 TZ

hehe. Sorry but it sounds funny to say an operator called := with overload opAssign is not related to overloading assignment. I would bet no matter what the symbol is and the overload name Walter's objections would still apply.

But they don't as far as I can see. Reading: http://www.digitalmars.com/d/faq.html#assignmentoverloading and remembering he mentioned something along the lines of "overloading = causes subtle behaviour which is a source of bugs for little gain". 1. := is a new operator, so no subtle behaviour for = is added. 2. You could argue := has the subtle behaviour, but I argue it isn't subtle because if you use := you're asking for that behaviour. 3. The copy constructor argument is on the surface valid, but consider intrinsics which have no constructors at all. 4. Lastly .dup does not solve the whole problem, the original intent was to make this possible: class A{} class B{} A a = new A(); B b; b = a; construct a A using an A. So while you can write a copy constructor: class A { this(B b) {} } intrinsics don't have constructors so in a template: template(T) { void foo(T t) { B b = new B(); T t; t = new T(b); }} it doesn't work when T is 'int' etc. .dup does not solve the above as: t = b.dup returns a B not a T. However := solves both problems neatly. t := b; calls opAssign for type T (for intrinsics it would do what it currently does on assignment). Regan
Apr 21 2005
parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
"Regan Heath" <regan netwin.co.nz> wrote in message 
news:opspln2nhw23k2f5 nrage.netwin.co.nz...
 On Thu, 21 Apr 2005 12:44:35 -0400, Ben Hinkle <ben.hinkle gmail.com> 
 wrote:
 "TechnoZeus" <TechnoZeus PeoplePC.com> wrote in message
 news:d48iic$9se$1 digitaldaemon.com...
 It's a big thread... that might have been in it somewhere.
 This branch of it deals with adding ":=" as a separate operator in
 addition to the "=" operator,
 and having ":=" act as a value assignment operator such that...
 a := b;
 anways results in (a == b) being true, but never makes (a is b) become
 true.

 Not related to overloading the "=" operator.

 TZ

hehe. Sorry but it sounds funny to say an operator called := with overload opAssign is not related to overloading assignment. I would bet no matter what the symbol is and the overload name Walter's objections would still apply.

But they don't as far as I can see. Reading: http://www.digitalmars.com/d/faq.html#assignmentoverloading and remembering he mentioned something along the lines of "overloading = causes subtle behaviour which is a source of bugs for little gain". 1. := is a new operator, so no subtle behaviour for = is added. 2. You could argue := has the subtle behaviour, but I argue it isn't subtle because if you use := you're asking for that behaviour.

I agree it's a matter of opinion what counts as subtle and what doesn't. The fact that users would know := can be subtle still makes it subtle. The argument that := isn't like = is too subtle for me ;-)
 3. The copy constructor argument is on the surface valid, but consider 
 intrinsics which have no constructors at all.

 4. Lastly .dup does not solve the whole problem, the original intent was 
 to make this possible:

 class A{}
 class B{}

 A a = new A();
 B b;

 b = a;

 construct a A using an A.

 So while you can write a copy constructor:

 class A {
  this(B b) {}
 }

 intrinsics don't have constructors so in a template:

 template(T) { void foo(T t) {
   B b = new B();
   T t;

   t = new T(b);
 }}

 it doesn't work when T is 'int' etc.

I think I need more context - I am missed the point.
 .dup does not solve the above as:
   t = b.dup

 returns a B not a T.


 However := solves both problems neatly.

 t := b;

 calls opAssign for type T (for intrinsics it would do what it currently 
 does on assignment).

I don't really get the point so correct me if I'm wrong but I think your example is getting at converting a B into a T while copying the value. I agree dup only concerns itself with duplicating a value and not with casting it or converting it to something else. For that one needs other mechanisms and I would agree it's hard to write generic code in D that does conversions. The opCast is clunky because you can't overload it. Personally I'm not convinced := is the right way to solve the casting problem, though. Consider if D got something that let you say "t = cast(T)b". That would be cleaner than introducing := IMO. If a copy of the value is needed it could be "t = cast(T)b.dup".
Apr 21 2005
next sibling parent "Regan Heath" <regan netwin.co.nz> writes:
On Thu, 21 Apr 2005 21:40:45 -0400, Ben Hinkle <ben.hinkle gmail.com>  
wrote:
 I don't really get the point so correct me if I'm wrong but I think your
 example is getting at converting a B into a T while copying the value.

Yes. Derek originally wanted to overload opCast by return type or something along those lines. After some thought I figured casting is actually just "copying the 'value' using some predefined method", i.e. casting from int to float copies the 'value' be it 5, 9 etc but uses some method to arrange the value in 'float' form. I also remembered a while back someone wanting a way to deep copy things. It occured to me a deep copy is also "copying the 'value' using some predefined method" where the source type is the same as the destination type. So then I figured, why not combine all these ideas into one thing, an operator that copies the 'value' from the RHS into the LHS, thus ":=".
 I agree dup only concerns itself with duplicating a value and not with  
 casting it or converting it to something else. For that one needs other  
 mechanisms and I would agree it's hard to write generic code in D that  
 does
 conversions. The opCast is clunky because you can't overload it.

Correct.
 Personally I'm not convinced := is the right way to solve the casting  
 problem, though.

I am not adverse to other suggestions...
 Consider if D got something that let you say "t = cast(T)b". That would  
 be cleaner than introducing := IMO.

Maybe. This would call some variant of opCast or something similar. Then you'd write a dup method when LHS and RHS are the same type. So you have opCast and dup methods, instead of opAssign methods. The latter just seems .. cleaner to me.
 If a copy of the value is needed it could be "t = cast(T)b.dup".

Wouldn't "t = cast(T)b" have to copy anyway? Regan
Apr 21 2005
prev sibling parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
Using := as a value assignment operator would have more uses than just those
related to casting.

Yes, it is true that there could be advantages in that area, but they would be
"emergent advantages" and would surface as a function of the implementation.

TZ
Apr 22 2005
prev sibling parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
"Ben Hinkle" <ben.hinkle gmail.com> wrote in message
news:d48l9l$cb7$1 digitaldaemon.com...
 "TechnoZeus" <TechnoZeus PeoplePC.com> wrote in message
 news:d48iic$9se$1 digitaldaemon.com...
 It's a big thread... that might have been in it somewhere.
 This branch of it deals with adding ":=" as a separate operator in
 addition to the "=" operator,
 and having ":=" act as a value assignment operator such that...
 a := b;
 anways results in (a == b) being true, but never makes (a is b) become
 true.

 Not related to overloading the "=" operator.

 TZ

hehe. Sorry but it sounds funny to say an operator called := with overload opAssign is not related to overloading assignment. I would bet no matter what the symbol is and the overload name Walter's objections would still apply. ps - I should have asked you to do my taxes :-)

Yes, you're right. If that had been what we were saying, it would have sounded funny. TZ
Apr 22 2005
prev sibling parent reply Georg Wrede <georg.wrede nospam.org> writes:
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.
Apr 21 2005
next sibling parent reply Brad Beveridge <brad somewhere.net> writes:
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.

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
Apr 21 2005
parent reply Derek Parnell <derek psych.ward> writes:
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
Apr 21 2005
parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
  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.
Apr 21 2005
parent Derek Parnell <derek psych.ward> writes:
On Thu, 21 Apr 2005 21:25:36 -0400, Ben Hinkle wrote:

  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.

Yes it would work, but I use templates a lot, and there are more classes than just two, so that might be a problem. The syntax "<id>.Value = <id>" is a bit more generic.
 Note the original example Foo.Value = b doesn't compile - I assume you meant 
 something like f.Value = b.

Oops! Just coding from the hip ;-) -- Derek Melbourne, Australia 22/04/2005 11:27:39 AM
Apr 21 2005
prev sibling parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
The problem isn't a lack of understanding.
The problem in comming to a uniform agreement is mostly in the idea that there
is only one right way to do something.
A few people who are comfortable with the way things are oppose the addition of
an alternative way of doing things because they see it as "not needed" since
they personally don't need it.

It's unfortunately an all too common way of looking at the world,
and if that way of thinking were to be applied across the board,
then since some people never program at all,
we could consider any programming language to be completely useless,
and since some people never use computers,
we could consider all computers to be useless as well.

In fact, if the only thing it takes for something to be useless is that
"someone" fails to see the use for it,
then by that logic, there is nothing in this world that is of any use at all.

Personally, I favor looking at the world from a less egocentric point of view.
If it's useful to "someone" then it is of value.

The := operator would "obviously" be of use to "many" people,
even if there are a few people who just don't see it.

TZ


"Georg Wrede" <georg.wrede nospam.org> wrote in message
news:42682A29.8090300 nospam.org...
 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.

Apr 22 2005
prev sibling parent Vladimir <kv11111 mail.ru> writes:
Vladimir wrote:

 /* Class for calculation some difficult function and caching result */
 /* Suppose reverse function is easy to calculate */
 class SomeFunction(T) {
         T _cached_val;
 
         T calculate(T input) {
                 /* if T is class we have seg-v here at first invocation
                  * because _cached_val is null */
                 if(input == calculate_reverse(_cached_val))

 2. reference-type variable are always initialized to null, while

One of possible solutions for this is to add static init property for classes: class A { /* example */ static A init = new A(0,0); /* evaluated only once */ /* default is: static A init = null; } */ } and then treat expression A a; as A a = A.init; (this is exactly the same as with fundamental types) so A a; A b; if((a is b) and (a is A.init)) writef(" true "); will print "true" -- Vladimir
Apr 21 2005
prev sibling parent reply "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
I should have been more clear in what I stated about pointers.
What I meant was that the :=" operator should effect "their own" value
(which is the address of what they are pointing to)
rather than the value of the anything that they might be pointing to.
In other words, that the value assignment operator should do direct value
assignemts.
No compromises.

I think a separate identity assignment operator would be overkill,
but I had included mention of it for completeness.

The addition of ".value" and ".identity" support would allow a way for
programmers to avoid any ambiguity,
which would probably not get used a lot in the long run,
but would definately be nice to have as an option...
especially for beginners who are not sure of whether something is a value type
or a reference type.
These members would allow them to treat "anything" as a value type,
or as a reference type (maybe it should be .reference rather than .identity?),
regardless of what it is...
and it would also be nice for searching the source code later.

As for +:= and so on... Not important at this time, but worth thinking about...
in my opinion.

Hopefully when Walter has time to look in here, he'll give the ":=" value
assignment operator strong consideration.
I don't know how he feels about bringing in programmers from different
backgrounds,
but I think the addition of a ":=" assignment operator would be a good step in
that direction,
due to people experienced in certain other languages finding it familliar and
comfortable.

TZ
Apr 20 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Wed, 20 Apr 2005 17:44:15 -0500, TechnoZeus <TechnoZeus PeoplePC.com>  
wrote:
 I should have been more clear in what I stated about pointers.
 What I meant was that the :=" operator should effect "their own" value
 (which is the address of what they are pointing to)
 rather than the value of the anything that they might be pointing to.

Just like "=" does currently.
 In other words, that the value assignment operator should do direct  
 value assignemts.
 No compromises.

 I think a separate identity assignment operator would be overkill,
 but I had included mention of it for completeness.

Then we are in agreement, pretty much.
 The addition of ".value" and ".identity" support would allow a way for  
 programmers to avoid any ambiguity,
 which would probably not get used a lot in the long run,
 but would definately be nice to have as an option...

Maybe, I'm not sold on the idea yet.
 especially for beginners who are not sure of whether something is a  
 value type or a reference type.
 These members would allow them to treat "anything" as a value type,
 or as a reference type (maybe it should be .reference rather than  
 .identity?),
 regardless of what it is...

But wouldn't this just train bad habits. Assuming using .value etc is only intended for beginners and you should really learn the difference between value and reference types.
 Hopefully when Walter has time to look in here, he'll give the ":="  
 value assignment operator strong consideration.

Fingers crossed. Regan
Apr 20 2005
parent reply "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
Yes, for the most part, we are in agreement... is one of the things I was
trying to clarify.
(stating it outright does tend to help.)

As for letting beginners use ".value" and ".identity" to avoid ambiguity,
I wouldn't consider than enforcing bad habits, but rather discouraging them.

After all, their code would be practically self-documented in that sense.
Those of us who have already gotten used to the way things are would be the
ones with
the bad habit of writing code that is harder for a person to be sure they
understood correctly.
Given time,
most new programmers would also adapt the simpler way over the less ambiguous
way,
but at least they would know that it's there in the event they're ever in
doubt...
or just want to write more readable code.  :)

TZ


"Regan Heath" <regan netwin.co.nz> wrote in message
news:opspjzn4ky23k2f5 nrage.netwin.co.nz...
 On Wed, 20 Apr 2005 17:44:15 -0500, TechnoZeus <TechnoZeus PeoplePC.com>
 wrote:
 I should have been more clear in what I stated about pointers.
 What I meant was that the :=" operator should effect "their own" value
 (which is the address of what they are pointing to)
 rather than the value of the anything that they might be pointing to.

Just like "=" does currently.
 In other words, that the value assignment operator should do direct
 value assignemts.
 No compromises.

 I think a separate identity assignment operator would be overkill,
 but I had included mention of it for completeness.

Then we are in agreement, pretty much.
 The addition of ".value" and ".identity" support would allow a way for
 programmers to avoid any ambiguity,
 which would probably not get used a lot in the long run,
 but would definately be nice to have as an option...

Maybe, I'm not sold on the idea yet.
 especially for beginners who are not sure of whether something is a
 value type or a reference type.
 These members would allow them to treat "anything" as a value type,
 or as a reference type (maybe it should be .reference rather than
 .identity?),
 regardless of what it is...

But wouldn't this just train bad habits. Assuming using .value etc is only intended for beginners and you should really learn the difference between value and reference types.
 Hopefully when Walter has time to look in here, he'll give the ":="
 value assignment operator strong consideration.

Fingers crossed. Regan

Apr 20 2005
parent reply Brad Beveridge <brad somewhere.net> writes:
I am soliticting help from the senior members of the NG.  As I mention 
in another thread, I would like to call a weigh in on this issue.
If I get 3 senior members (I mention specific names in the Walter Weigh 
In thread, but if I have missed anyone please speak up) saying that 
introducing ":=" as a deepcopy operator is a good idea, then I will 
summerize this thread and rename it to
"Walter Weigh In: How to bridge the gap between user defined types and 
built in types"

Can I please have sanction from at least three of the more senior people 
here.

Thanks
Brad
Apr 20 2005
parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
I'll do one better than that.

TZ

"Brad Beveridge" <brad somewhere.net> wrote in message
news:d46qs6$1jpt$1 digitaldaemon.com...
 I am soliticting help from the senior members of the NG.  As I mention
 in another thread, I would like to call a weigh in on this issue.
 If I get 3 senior members (I mention specific names in the Walter Weigh
 In thread, but if I have missed anyone please speak up) saying that
 introducing ":=" as a deepcopy operator is a good idea, then I will
 summerize this thread and rename it to
 "Walter Weigh In: How to bridge the gap between user defined types and
 built in types"

 Can I please have sanction from at least three of the more senior people
 here.

 Thanks
 Brad

Apr 20 2005
prev sibling parent reply Christian Schüler <Christian_member pathlink.com> writes:
With respect to the established mathematical notation,

:= should by the identity assignment






In article <opspa0gry023k2f5 nrage.netwin.co.nz>, Regan Heath says...
To get some idea of context you're best to read the entire thread, tho  
it's a big one.. so, to make life easier I'm going to attempt to summarise  
it. (if anyone has corrections, please make them)

In essence Derek wanted to assign the value of an object with another. His  
initial idea was to use an overload of the assingment operator, as is done  
in C++.

D does not allow you to overload the assignment operator, I believe,  
because Walter dislikes the subtle behaviour this introduces, and in his  
experience subtle bugs can arise out of it.

Classes are references and assignment '=' does a reference assignment.  
Overloading '=' to do a value assignment for a class would change this  
behaviour.

So, how to solve Dereks requirement of a value assignment for a reference  
type.

It occured to me that this was identical to a "deep copy" where the object  
being assigned was the same type as the value being assigned.

So, "to kill 2 birds with one stone" (AKA solve both problems at once) I  
figured a value assignment operator was required. I remember someone  
talking about ":=" and it's use in other languages, tho I've never used  
them, so I suggested it.

It also occured to me that we have "==" and "is" for value and identity  
comparisons (albeit with exceptions - IMO sensible ones) and it therefore  
makes sense to have ":=" and "=" for value and identity assignments  
(interestingly with all the same exceptions as "==" and "is" operate  
under).

My take on "==" and "is" (for reference):

1. "==" does value comparison.
2. "is" does identity comparison.

Exception to 1, a reference type with no defined method of comparison is  
compared using identity. If identity is equal, value will be equal. If  
identity is not equal then given no way to compare value one must assume  
inequality or throw an exception. (D assumes inequality, an exception can  
be thrown by coding it manually)

Exception to 2, a value type. No 2 values types can compare equal in  
identity. Technically this could be an error? However, D does a value  
comparison. A lint program could catch and error on this. I see little  
point and quite like the way "if (a is 5)" (where a is an 'int' or  
similar) reads.

How these exceptions apply to "=" and ":=":

1. ":=" does value assignment
2. "="  does identity assignment

Exception to 1, a reference type with no defined method of assignment.  
Best behaviour here would be an error IMO.

Exception to 2, a value type. You cannot assign identity to a value type,  
so you assign value (current D behaviour).

So, as you can see the exceptions are parallel, the behvaiour of "=" need  
not change, all that is added is ":=" and opAssign overloads for reference  
types.

Regan

On Fri, 15 Apr 2005 21:00:25 +0400, Vladimir <kv11111 mail.ru> wrote:
 TechnoZeus wrote:

 Oops... my apologies, Vladimir.  I thought I was reading Ben's post.   
 Had
 clicked on it in the list, and somehow got yours... didn't notice the
 signature, until just as I clicked the "send" button.

 Sorry about the confusion.  Anyway... Thanks for the great idea  
 Vladimir.
 Please elaborate.

Actually this is not my idea, look at the thread called opValue at the and of discussion. But I really like this idea and think it's very important. The only trouble is to convince Walter to allow this operator. For quick explanation, this it the extraction from that thread: ,--------------- Forwarded message (begin) Subject: Re: opValue() From: Regan Heath <regan netwin.co.nz> Date: Thu, 07 Apr 2005 05:34:52 +0400 Newsgroup: digitalmars.D On Thu, 07 Apr 2005 08:45:21 +1200, <brad domain.invalid> wrote: > rter syntax: >> class T { T opShlAssign(Foo c) { /*...*/ return this; } } >> a<<=b; // almost like a=b, if you ask me >> I guess in 99.99999% cases, shifting an object to left with another >> object doesn't make sense anyway, so the operator might as well get >> another use.. >> xs0 > > Argh! Surely not! I thought one of the philosophies of D was that > operators should _always_ do what you expect. The <<= operator should > always shift left & assign. > > Derek - am I right in saying that you want an assignment operator that > doesn't create a new object, but instead alters an existing one? At the > moment, when you deal with objects/references, the = operator always > means "set this reference to this object". I don't think that it makes > sense to overload this meaning, because you then end up with an operator > that in some cases does > "set this reference to this object" and in other cases > "alter the internal data layout of object A, based on the values in > object B" > And then you end up with a whole lot of special rules to try and > remember which assignment operator is applying. Overwriting the > contents of an object when you really ment to assign to a new object > could ruin your day if you hold multiple references to the object you > are stomping on. > > I am in favour of having an operator that means "take object B, get some > values out of it and setup object A accordingly" And if they're the same type, it could be used for a "deep-copy"? I think we can combine this casting concern with the deep-copy concern, they seem closely related to me.
 Something like

> Bar b = new Bar (); > a <- b // which calls a.opConvert(b); > > I guess you could also end up with nasty > a = (new Foo())<- b; It seems 'correct' if 'ugly', done in 2 steps looks nicer and incurs no additional penalty (that I can see). a = new Foo(); a <- b; this operator is really a "copy RHS into LHS" operator, which implys that LHS must exists beforehand. Or using the "<-" operator could implicitly call new if the LHS is null... not sure how feasible that is.
 <- is probably not the operator to choose, probably hard to parse.  

> someone else can think of a good operator if this functionality is > required. I agree, I think the main concern against this in Walters case was that implicit conversion when "=" is used can cause subtle behaviour and bugs. (correct me if I am wrong). So, if a new operator was used, eg. ":=" or something then this concern vanishes, as "=" does what it currently does: - shallow copy for arrays. - reference assignment for classes etc - deep copy for value types The new ":=" operator always means "copy RHS into LHS" AKA: - deep copy for arrays (provided items in array have deep-copy method defined) - deep copy for classes (provided class has deep-copy method defined) - same as "=" for value types. Thoughts? Regan `--------------- Forwarded message (end)


Apr 20 2005
parent reply "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
Why?

TZ

"Christian Schüler" <Christian_member pathlink.com> wrote in message
news:d46omi$1hsn$1 digitaldaemon.com...
 With respect to the established mathematical notation,

 := should by the identity assignment






 In article <opspa0gry023k2f5 nrage.netwin.co.nz>, Regan Heath says...
To get some idea of context you're best to read the entire thread, tho
it's a big one.. so, to make life easier I'm going to attempt to summarise
it. (if anyone has corrections, please make them)

In essence Derek wanted to assign the value of an object with another. His
initial idea was to use an overload of the assingment operator, as is done
in C++.

D does not allow you to overload the assignment operator, I believe,
because Walter dislikes the subtle behaviour this introduces, and in his
experience subtle bugs can arise out of it.

Classes are references and assignment '=' does a reference assignment.
Overloading '=' to do a value assignment for a class would change this
behaviour.

So, how to solve Dereks requirement of a value assignment for a reference
type.

It occured to me that this was identical to a "deep copy" where the object
being assigned was the same type as the value being assigned.

So, "to kill 2 birds with one stone" (AKA solve both problems at once) I
figured a value assignment operator was required. I remember someone
talking about ":=" and it's use in other languages, tho I've never used
them, so I suggested it.

It also occured to me that we have "==" and "is" for value and identity
comparisons (albeit with exceptions - IMO sensible ones) and it therefore
makes sense to have ":=" and "=" for value and identity assignments
(interestingly with all the same exceptions as "==" and "is" operate
under).

My take on "==" and "is" (for reference):

1. "==" does value comparison.
2. "is" does identity comparison.

Exception to 1, a reference type with no defined method of comparison is
compared using identity. If identity is equal, value will be equal. If
identity is not equal then given no way to compare value one must assume
inequality or throw an exception. (D assumes inequality, an exception can
be thrown by coding it manually)

Exception to 2, a value type. No 2 values types can compare equal in
identity. Technically this could be an error? However, D does a value
comparison. A lint program could catch and error on this. I see little
point and quite like the way "if (a is 5)" (where a is an 'int' or
similar) reads.

How these exceptions apply to "=" and ":=":

1. ":=" does value assignment
2. "="  does identity assignment

Exception to 1, a reference type with no defined method of assignment.
Best behaviour here would be an error IMO.

Exception to 2, a value type. You cannot assign identity to a value type,
so you assign value (current D behaviour).

So, as you can see the exceptions are parallel, the behvaiour of "=" need
not change, all that is added is ":=" and opAssign overloads for reference
types.

Regan

On Fri, 15 Apr 2005 21:00:25 +0400, Vladimir <kv11111 mail.ru> wrote:
 TechnoZeus wrote:

 Oops... my apologies, Vladimir.  I thought I was reading Ben's post.
 Had
 clicked on it in the list, and somehow got yours... didn't notice the
 signature, until just as I clicked the "send" button.

 Sorry about the confusion.  Anyway... Thanks for the great idea
 Vladimir.
 Please elaborate.

Actually this is not my idea, look at the thread called opValue at the and of discussion. But I really like this idea and think it's very important. The only trouble is to convince Walter to allow this operator. For quick explanation, this it the extraction from that thread: ,--------------- Forwarded message (begin) Subject: Re: opValue() From: Regan Heath <regan netwin.co.nz> Date: Thu, 07 Apr 2005 05:34:52 +0400 Newsgroup: digitalmars.D On Thu, 07 Apr 2005 08:45:21 +1200, <brad domain.invalid> wrote: > rter syntax: >> class T { T opShlAssign(Foo c) { /*...*/ return this; } } >> a<<=b; // almost like a=b, if you ask me >> I guess in 99.99999% cases, shifting an object to left with another >> object doesn't make sense anyway, so the operator might as well get >> another use.. >> xs0 > > Argh! Surely not! I thought one of the philosophies of D was that > operators should _always_ do what you expect. The <<= operator should > always shift left & assign. > > Derek - am I right in saying that you want an assignment operator that > doesn't create a new object, but instead alters an existing one? At the > moment, when you deal with objects/references, the = operator always > means "set this reference to this object". I don't think that it makes > sense to overload this meaning, because you then end up with an operator > that in some cases does > "set this reference to this object" and in other cases > "alter the internal data layout of object A, based on the values in > object B" > And then you end up with a whole lot of special rules to try and > remember which assignment operator is applying. Overwriting the > contents of an object when you really ment to assign to a new object > could ruin your day if you hold multiple references to the object you > are stomping on. > > I am in favour of having an operator that means "take object B, get some > values out of it and setup object A accordingly" And if they're the same type, it could be used for a "deep-copy"? I think we can combine this casting concern with the deep-copy concern, they seem closely related to me.
 Something like

> Bar b = new Bar (); > a <- b // which calls a.opConvert(b); > > I guess you could also end up with nasty > a = (new Foo())<- b; It seems 'correct' if 'ugly', done in 2 steps looks nicer and incurs no additional penalty (that I can see). a = new Foo(); a <- b; this operator is really a "copy RHS into LHS" operator, which implys that LHS must exists beforehand. Or using the "<-" operator could implicitly call new if the LHS is null... not sure how feasible that is.
 <- is probably not the operator to choose, probably hard to parse.

> someone else can think of a good operator if this functionality is > required. I agree, I think the main concern against this in Walters case was that implicit conversion when "=" is used can cause subtle behaviour and bugs. (correct me if I am wrong). So, if a new operator was used, eg. ":=" or something then this concern vanishes, as "=" does what it currently does: - shallow copy for arrays. - reference assignment for classes etc - deep copy for value types The new ":=" operator always means "copy RHS into LHS" AKA: - deep copy for arrays (provided items in array have deep-copy method defined) - deep copy for classes (provided class has deep-copy method defined) - same as "=" for value types. Thoughts? Regan `--------------- Forwarded message (end)



Apr 20 2005
parent reply Christian Schüler <Christian_member pathlink.com> writes:
Just as I was expecting that a google search on "mathematical identity" would
turn up loads of examples, it fails on me...

The proper symbol for identity is really U+2261, "identity", a = with 3 dashes.

Besides that, I recall := being used in mathematical context for expressing
identity as opposed to equal values, which is what = stands for.





In article <d46pk7$1ii7$1 digitaldaemon.com>, TechnoZeus says...
Why?

TZ

"Christian Schüler" <Christian_member pathlink.com> wrote in message
news:d46omi$1hsn$1 digitaldaemon.com...
 With respect to the established mathematical notation,

 := should by the identity assignment






 In article <opspa0gry023k2f5 nrage.netwin.co.nz>, Regan Heath says...
To get some idea of context you're best to read the entire thread, tho
it's a big one.. so, to make life easier I'm going to attempt to summarise
it. (if anyone has corrections, please make them)

In essence Derek wanted to assign the value of an object with another. His
initial idea was to use an overload of the assingment operator, as is done
in C++.

D does not allow you to overload the assignment operator, I believe,
because Walter dislikes the subtle behaviour this introduces, and in his
experience subtle bugs can arise out of it.

Classes are references and assignment '=' does a reference assignment.
Overloading '=' to do a value assignment for a class would change this
behaviour.

So, how to solve Dereks requirement of a value assignment for a reference
type.

It occured to me that this was identical to a "deep copy" where the object
being assigned was the same type as the value being assigned.

So, "to kill 2 birds with one stone" (AKA solve both problems at once) I
figured a value assignment operator was required. I remember someone
talking about ":=" and it's use in other languages, tho I've never used
them, so I suggested it.

It also occured to me that we have "==" and "is" for value and identity
comparisons (albeit with exceptions - IMO sensible ones) and it therefore
makes sense to have ":=" and "=" for value and identity assignments
(interestingly with all the same exceptions as "==" and "is" operate
under).

My take on "==" and "is" (for reference):

1. "==" does value comparison.
2. "is" does identity comparison.

Exception to 1, a reference type with no defined method of comparison is
compared using identity. If identity is equal, value will be equal. If
identity is not equal then given no way to compare value one must assume
inequality or throw an exception. (D assumes inequality, an exception can
be thrown by coding it manually)

Exception to 2, a value type. No 2 values types can compare equal in
identity. Technically this could be an error? However, D does a value
comparison. A lint program could catch and error on this. I see little
point and quite like the way "if (a is 5)" (where a is an 'int' or
similar) reads.

How these exceptions apply to "=" and ":=":

1. ":=" does value assignment
2. "="  does identity assignment

Exception to 1, a reference type with no defined method of assignment.
Best behaviour here would be an error IMO.

Exception to 2, a value type. You cannot assign identity to a value type,
so you assign value (current D behaviour).

So, as you can see the exceptions are parallel, the behvaiour of "=" need
not change, all that is added is ":=" and opAssign overloads for reference
types.

Regan

On Fri, 15 Apr 2005 21:00:25 +0400, Vladimir <kv11111 mail.ru> wrote:
 TechnoZeus wrote:

 Oops... my apologies, Vladimir.  I thought I was reading Ben's post.
 Had
 clicked on it in the list, and somehow got yours... didn't notice the
 signature, until just as I clicked the "send" button.

 Sorry about the confusion.  Anyway... Thanks for the great idea
 Vladimir.
 Please elaborate.

Actually this is not my idea, look at the thread called opValue at the and of discussion. But I really like this idea and think it's very important. The only trouble is to convince Walter to allow this operator. For quick explanation, this it the extraction from that thread: ,--------------- Forwarded message (begin) Subject: Re: opValue() From: Regan Heath <regan netwin.co.nz> Date: Thu, 07 Apr 2005 05:34:52 +0400 Newsgroup: digitalmars.D On Thu, 07 Apr 2005 08:45:21 +1200, <brad domain.invalid> wrote: > rter syntax: >> class T { T opShlAssign(Foo c) { /*...*/ return this; } } >> a<<=b; // almost like a=b, if you ask me >> I guess in 99.99999% cases, shifting an object to left with another >> object doesn't make sense anyway, so the operator might as well get >> another use.. >> xs0 > > Argh! Surely not! I thought one of the philosophies of D was that > operators should _always_ do what you expect. The <<= operator should > always shift left & assign. > > Derek - am I right in saying that you want an assignment operator that > doesn't create a new object, but instead alters an existing one? At the > moment, when you deal with objects/references, the = operator always > means "set this reference to this object". I don't think that it makes > sense to overload this meaning, because you then end up with an operator > that in some cases does > "set this reference to this object" and in other cases > "alter the internal data layout of object A, based on the values in > object B" > And then you end up with a whole lot of special rules to try and > remember which assignment operator is applying. Overwriting the > contents of an object when you really ment to assign to a new object > could ruin your day if you hold multiple references to the object you > are stomping on. > > I am in favour of having an operator that means "take object B, get some > values out of it and setup object A accordingly" And if they're the same type, it could be used for a "deep-copy"? I think we can combine this casting concern with the deep-copy concern, they seem closely related to me.
 Something like

> Bar b = new Bar (); > a <- b // which calls a.opConvert(b); > > I guess you could also end up with nasty > a = (new Foo())<- b; It seems 'correct' if 'ugly', done in 2 steps looks nicer and incurs no additional penalty (that I can see). a = new Foo(); a <- b; this operator is really a "copy RHS into LHS" operator, which implys that LHS must exists beforehand. Or using the "<-" operator could implicitly call new if the LHS is null... not sure how feasible that is.
 <- is probably not the operator to choose, probably hard to parse.

> someone else can think of a good operator if this functionality is > required. I agree, I think the main concern against this in Walters case was that implicit conversion when "=" is used can cause subtle behaviour and bugs. (correct me if I am wrong). So, if a new operator was used, eg. ":=" or something then this concern vanishes, as "=" does what it currently does: - shallow copy for arrays. - reference assignment for classes etc - deep copy for value types The new ":=" operator always means "copy RHS into LHS" AKA: - deep copy for arrays (provided items in array have deep-copy method defined) - deep copy for classes (provided class has deep-copy method defined) - same as "=" for value types. Thoughts? Regan `--------------- Forwarded message (end)




Apr 20 2005
parent reply Brad Beveridge <brad somewhere.net> writes:
Christian Schüler wrote:
 Just as I was expecting that a google search on "mathematical identity" would
 turn up loads of examples, it fails on me...
 
 The proper symbol for identity is really U+2261, "identity", a = with 3 dashes.
 
 Besides that, I recall := being used in mathematical context for expressing
 identity as opposed to equal values, which is what = stands for.
 

operator we choose is particularly relevant. I think that ":=" was adopted because it has the "=" sign in it, it looks like an assignment operation, and Pascal programmers will be familiar with it. I think it would be folly to try to use "=" for deep copy, and ":=" for what we currently use "=" for. Anyhow - the real core of the issue is that many of us feel a "deep copy" operator makes sense. Brad
Apr 20 2005
next sibling parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
Yep... I totally agree.  Better to let "=" act as it does now, and let ":="
assign by copying the contents of the source item into the destination item.

As for the established mathematical identity operator, I would recommend that
for identity comparisons, except that I've never seen a keyboard with that
symbol on it.


TZ

"Brad Beveridge" <brad somewhere.net> wrote in message
news:d46t6k$1lja$1 digitaldaemon.com...
 Christian Schüler wrote:
 Just as I was expecting that a google search on "mathematical identity" would
 turn up loads of examples, it fails on me...

 The proper symbol for identity is really U+2261, "identity", a = with 3 dashes.

 Besides that, I recall := being used in mathematical context for expressing
 identity as opposed to equal values, which is what = stands for.

operator we choose is particularly relevant. I think that ":=" was adopted because it has the "=" sign in it, it looks like an assignment operation, and Pascal programmers will be familiar with it. I think it would be folly to try to use "=" for deep copy, and ":=" for what we currently use "=" for. Anyhow - the real core of the issue is that many of us feel a "deep copy" operator makes sense. Brad

Apr 20 2005
prev sibling parent reply Kevin Bealer <Kevin_member pathlink.com> writes:
In article <d46t6k$1lja$1 digitaldaemon.com>, Brad Beveridge says...
Christian Schüler wrote:
 Just as I was expecting that a google search on "mathematical identity" would
 turn up loads of examples, it fails on me...
 
 The proper symbol for identity is really U+2261, "identity", a = with 3 dashes.
 
 Besides that, I recall := being used in mathematical context for expressing
 identity as opposed to equal values, which is what = stands for.
 

operator we choose is particularly relevant. I think that ":=" was adopted because it has the "=" sign in it, it looks like an assignment operation, and Pascal programmers will be familiar with it. I think it would be folly to try to use "=" for deep copy, and ":=" for what we currently use "=" for. Anyhow - the real core of the issue is that many of us feel a "deep copy" operator makes sense. Brad

What can you do with deep copy that you can't do with: a = b.dup; Or, do you mean "deeper" than that, as in, keep descending levels? Or is efficiency the primary reason to do a deep copy instead of that syntax? Kevin
Apr 22 2005
parent reply Brad Beveridge <brad somewhere.net> writes:
 
 What can you do with deep copy that you can't do with:
 
 a = b.dup;
 
 Or, do you mean "deeper" than that, as in, keep descending levels?  Or is
 efficiency the primary reason to do a deep copy instead of that syntax?
 
 Kevin
 

Yes, I think that you should be able to override a function so that a deep copy descends levels. But the primary problem with b.dup is that it doesn't work for built-in types. Also in this discussion is the problem that you there is no way to fill out an object of type Foo from an object of type Bar, with C++ you could just override operator= so that a = b; would actually convert/copy b into a. Cheers Brad
Apr 22 2005
parent reply "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
As I pointed out in another thread, the following code doesn't work...

//_______________________________//
char[] source = "This is just for testing purposes.";
char[4] dest;
void main()
{
 dest = source[8..12].dup;
 assert(dest=="just");
}
//_______________________________//

So using .dup doesn't actually emulate a value assignment operator.

For clarification, in the following code...

//_______________________________//
char[] source = "This is just for testing purposes.";
char[4] dest;
void main()
{
 dest := source[8..12];
 assert(dest=="just");
}
//_______________________________//

the line...

 dest := source[8..12];

...would mean set the contents of "dest" to the contents of "source[8..12]"

The value assignment operator would assign values.  Not identities.

If there are cases which Walter thinks are ambiguous, I would rather he simply
leave no definition for the ":=" operator in those cases than to leave us
without a value assignment operator over it... even if we're not given a way to
be able to define the operator for those cases.

TZ




"Brad Beveridge" <brad somewhere.net> wrote in message
news:d4cp3i$v7c$1 digitaldaemon.com...
 What can you do with deep copy that you can't do with:

 a = b.dup;

 Or, do you mean "deeper" than that, as in, keep descending levels?  Or is
 efficiency the primary reason to do a deep copy instead of that syntax?

 Kevin

Yes, I think that you should be able to override a function so that a deep copy descends levels. But the primary problem with b.dup is that it doesn't work for built-in types. Also in this discussion is the problem that you there is no way to fill out an object of type Foo from an object of type Bar, with C++ you could just override operator= so that a = b; would actually convert/copy b into a. Cheers Brad

Apr 23 2005
parent reply "Carlos Santander B." <csantander619 gmail.com> writes:
TechnoZeus wrote:
 As I pointed out in another thread, the following code doesn't work...
 
 //_______________________________//
 char[] source = "This is just for testing purposes.";
 char[4] dest;
 void main()
 {
  dest = source[8..12].dup;
  assert(dest=="just");
 }
 //_______________________________//
 
 So using .dup doesn't actually emulate a value assignment operator.

It was already answered: this is almost as trying to change a const.
 
 For clarification, in the following code...
 
 //_______________________________//
 char[] source = "This is just for testing purposes.";
 char[4] dest;
 void main()
 {
  dest := source[8..12];
  assert(dest=="just");
 }
 //_______________________________//
 
 the line...
 
  dest := source[8..12];
 
 ....would mean set the contents of "dest" to the contents of "source[8..12]"

Also already answered: dest[] = source[8..12] -- Carlos Santander Bernal
Apr 23 2005
parent reply "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
"Carlos Santander B." <csantander619 gmail.com> wrote in message
news:d4evp8$2qpv$1 digitaldaemon.com...
 TechnoZeus wrote:
 As I pointed out in another thread, the following code doesn't work...

 //_______________________________//
 char[] source = "This is just for testing purposes.";
 char[4] dest;
 void main()
 {
  dest = source[8..12].dup;
  assert(dest=="just");
 }
 //_______________________________//

 So using .dup doesn't actually emulate a value assignment operator.

It was already answered: this is almost as trying to change a const.
 For clarification, in the following code...

 //_______________________________//
 char[] source = "This is just for testing purposes.";
 char[4] dest;
 void main()
 {
  dest := source[8..12];
  assert(dest=="just");
 }
 //_______________________________//

 the line...

  dest := source[8..12];

 ....would mean set the contents of "dest" to the contents of "source[8..12]"

Also already answered: dest[] = source[8..12] -- Carlos Santander Bernal

That's not an answer. It's a work-around. dest is an array, in that example, not a pointer. It should be possible to assign the contents of an array to an array. I like the way it is handled with the "=" operator, overall, but my point is that .dup doesn't change what you're working with into something that acts like a value type, so the "=" operator thinks you want to change the destination to point to the contents of the duplicate. A value assignment operator wouldn't have to "figure out" whether you wanted to change the value or the identity of the destination operand. TZ
Apr 23 2005
parent reply Derek Parnell <derek psych.ward> writes:
On Sat, 23 Apr 2005 23:41:30 -0500, TechnoZeus wrote:

 "Carlos Santander B." <csantander619 gmail.com> wrote in message
news:d4evp8$2qpv$1 digitaldaemon.com...
 TechnoZeus wrote:
 As I pointed out in another thread, the following code doesn't work...

 //_______________________________//
 char[] source = "This is just for testing purposes.";
 char[4] dest;
 void main()
 {
  dest = source[8..12].dup;
  assert(dest=="just");
 }
 //_______________________________//

 So using .dup doesn't actually emulate a value assignment operator.

It was already answered: this is almost as trying to change a const.
 For clarification, in the following code...

 //_______________________________//
 char[] source = "This is just for testing purposes.";
 char[4] dest;
 void main()
 {
  dest := source[8..12];
  assert(dest=="just");
 }
 //_______________________________//

 the line...

  dest := source[8..12];

 ....would mean set the contents of "dest" to the contents of "source[8..12]"

Also already answered: dest[] = source[8..12] -- Carlos Santander Bernal

That's not an answer. It's a work-around.

Are doing this deliberately? That is not a work around. It is the way to do it.
 dest is an array, in that example, not a pointer.

 It should be possible to assign the contents of an array to an array.

It is. And the way one does it is to specify which elements of the target array you are updating. The syntax 'target[]' is shorthand for 'target[0..$]'. Even in the case where the target is a dynamic array, target = source; does not update the target array elements, it makes target point to the same array as source. To update the elements you still need to do target[] = source;
 I like the way it is handled with the "=" operator, overall, but
 my point is that .dup doesn't change what you're working with into
 something that acts like a value type,

Of course not. The .dup just takes a copy.
 so the "=" operator thinks you want to change the destination
 to point to the contents of the duplicate.

Yes, because that's what you told it to do via the 'target = source;' statement. If you wanted to update all the elements in target, you need to use the correct syntax... 'target[] = source'
 A value assignment operator wouldn't have to "figure out"
 whether you wanted to change the value or the identity of
 the destination operand.

You seem to be saying, that you wish ':=' to be an alternative syntax to update all the elements in an array, based on the elements in the source. -- Derek Parnell Melbourne, Australia http://www.dsource.org/projects/build 24/04/2005 8:50:16 PM
Apr 24 2005
parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
"Derek Parnell" <derek psych.ward> wrote in message
news:nvs7ocyuwj7$.5srfzovygnpv$.dlg 40tude.net...
 On Sat, 23 Apr 2005 23:41:30 -0500, TechnoZeus wrote:

 You seem to be saying, that you wish ':=' to be an alternative syntax to
 update all the elements in an array, based on the elements in the source.

 -- 
 Derek Parnell
 Melbourne, Australia
 http://www.dsource.org/projects/build
 24/04/2005 8:50:16 PM

Among othger things, yes... that is what I am saying I would like it to do. More generally, I would like := to update the contents of the destination operand with the contents of the source operand. That's what value assignment is. As for source being a dynamic array reference rather than an array, I think that is a matter of perspective. The "=" operator does treat it as a dynamic array reference, we all know there's more to "what it is" than simply how it's treated. I'm not tring to tell anyone that their point of view is wrong. I'm trying to point out that alternative points of view may be equally valid, and potentially productive. Having a value assignment operator available would support an alternative way of thinking, and by extension, increase potential productivity. People who don't like it wouldn't have to use it. People who do like it wouldn't have to use it "exclusively". TZ
Apr 24 2005
prev sibling parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
 Thanks Ben.

 Okay, now... Ben...

I think you mean Vladimir. My post was the one with no ideas in it :-)
Apr 15 2005
parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
Hahaha.  Cute, Ben.  Yes, I was responding to Vladimir's post, and thought it
was yours.  Mouse click error, I think.  Already responded to my own post with
information to that effect.  Sorry for the error.

TZ

"Ben Hinkle" <ben.hinkle gmail.com> wrote in message
news:d3o9bc$711$1 digitaldaemon.com...
 Thanks Ben.

 Okay, now... Ben...

I think you mean Vladimir. My post was the one with no ideas in it :-)

Apr 15 2005
prev sibling parent reply "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
Anders mentioned the addition of a ":=" operator on April 12th,
and then there is this one,
to which I am posting a reply,
and the discussion has resulted in what looks suspiciously like nearly
unanimous agreement...
so as has been pointed out more than once,
it's time to ask Walter to have a look at it.

Walter: Please consider the addition of ":=" as a vlaue assignment operator.

What's meant by that, is while "=" would continue to function "as is" there
would be the option of using ":=" to represent assignment of value regardless
of whether dealing with value types or reverence types.

In cases where assigning value can't be done, ":=" would produce an error
rather than assign by identity.  This would allow unambiguous source code, and
would also point out any places where there may be a need to add a value
assignment specifically.

Please give us some indication of what you think on this matter.  Many of us
would very much like to see this implemented, and feel that it would be very
beneficial.

Donald A. Kronos, PhD. - TechnoZeus


"Vladimir" <kv11111 mail.ru> wrote in message
news:d3o2ho$al$1 digitaldaemon.com...
 BTW, the simple workaround about general templates. Inside template one
 could write
 a=b+0;
 instead of
 a=b;
 to emulate assignment by value.

 But in my opinion having something like ":=" operator is much more
 convenient.

 -- 
           Vladimir

Apr 20 2005
parent reply "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
I'm inviting anyone who wants to summarize their thoughts or comments on the
proposed ":=" assignment opperator to do so as a reply to this post...
to save Walter the time necessary to otherwise search for such comments.

TechnoZeus
Apr 20 2005
next sibling parent reply Brad Beveridge <brad somewhere.net> writes:
TechnoZeus wrote:
 I'm inviting anyone who wants to summarize their thoughts or comments on the
proposed ":=" assignment opperator to do so as a reply to this post...
 to save Walter the time necessary to otherwise search for such comments.
 
 TechnoZeus
 
 

The flexibility of the ":=" operator is twofold if it calls an "opAssign" function when used with LHS being a class. Calling opAssign (or some other name) because then you not only have the deep copy ability, but you can cast/convert from one class type to another. ie Foo a = new Foo(); Foo b = new Foo(); Bar c = new Bar(); a := b; // calls Foo.opAssign(Foo rhs); a := c; // calls Foo.opAssign(Bar rhs); Also, array.dup can now go away. Brad
Apr 20 2005
next sibling parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
Cool.  Hadn't thought of that.  :)

Now I'm wondering how many other "unexpected" potential benefits there might be.

Other comments?

TZ

"Brad Beveridge" <brad somewhere.net> wrote in message
news:d46u5v$1mi8$1 digitaldaemon.com...
 TechnoZeus wrote:
 I'm inviting anyone who wants to summarize their thoughts or comments on the
proposed ":=" assignment opperator to do so as a reply to this post...
 to save Walter the time necessary to otherwise search for such comments.

 TechnoZeus

The flexibility of the ":=" operator is twofold if it calls an "opAssign" function when used with LHS being a class. Calling opAssign (or some other name) because then you not only have the deep copy ability, but you can cast/convert from one class type to another. ie Foo a = new Foo(); Foo b = new Foo(); Bar c = new Bar(); a := b; // calls Foo.opAssign(Foo rhs); a := c; // calls Foo.opAssign(Bar rhs); Also, array.dup can now go away. Brad

Apr 20 2005
prev sibling parent "Ben Hinkle" <bhinkle mathworks.com> writes:
 Foo a = new Foo();
 Foo b = new Foo();
 Bar c = new Bar();
 a := b; // calls Foo.opAssign(Foo rhs);
 a := c; // calls Foo.opAssign(Bar rhs);

 Also, array.dup can now go away.

array.dup would still be needed (like any dup property) in expressions that don't have any assignment. For example "return array.dup;"
Apr 21 2005
prev sibling parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
"TechnoZeus" <TechnoZeus PeoplePC.com> wrote in message 
news:d46tp4$1m37$1 digitaldaemon.com...
 I'm inviting anyone who wants to summarize their thoughts or comments on 
 the proposed ":=" assignment opperator to do so as a reply to this post...
 to save Walter the time necessary to otherwise search for such comments.

What exactly is the proposed behavior? For instance what would it do for builtin types, pointers, arrays, structs, and classes? The post with [suggestion][Walter] in the subject mentions "assign by value" but that's too vague for me. For example how deep does the deep assignment go? I haven't looked at all the other posts in the thread but I'd be surprised if this is really the right way to address the problem. Actually now that I think of it - what is the problem? I assume it's that inside templates "=" assigns by value for value types and by reference for reference types, correct? Plus I skimmed a post or two about a problem that there is an asymmetry between "==" and "is" and assignment (which only has "="). About the template problem: I'd prefer to look into something like extending ".dup" to all types rather than invent a new operator. But I haven't thought about it really. About the asymmetry problem: D is designed to be practical so while it would be nice to have symmetry I wouldn't consider that a goal.
Apr 20 2005
next sibling parent reply Brad Beveridge <brad somewhere.net> writes:
 What exactly is the proposed behavior? For instance what would it do for 
 builtin types, pointers, arrays, structs, and classes? The post with 
 [suggestion][Walter] in the subject mentions "assign by value" but that's 
 too vague for me. For example how deep does the deep assignment go?
 

Built-in types will behave exactly as they do with ":=" as they currently do with "=" Arrays will have a new array created, with each new element created from the old array using the ":=" operator. Structs will have ":=" called on each member they contain - or if this is too hard, they will need to define opAssign(). Reference types (ie classes) will need to define the operator function opAssign, and they can do what they like. Classes may also define overloaded opAssign functions, which could potentially act as object conversion operators. Brad
Apr 20 2005
parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
"Brad Beveridge" <brad somewhere.net> wrote in message
news:d46vid$1nec$1 digitaldaemon.com...
 What exactly is the proposed behavior? For instance what would it do for
 builtin types, pointers, arrays, structs, and classes? The post with
 [suggestion][Walter] in the subject mentions "assign by value" but that's
 too vague for me. For example how deep does the deep assignment go?

Built-in types will behave exactly as they do with ":=" as they currently do with "=" Arrays will have a new array created, with each new element created from the old array using the ":=" operator. Structs will have ":=" called on each member they contain - or if this is too hard, they will need to define opAssign(). Reference types (ie classes) will need to define the operator function opAssign, and they can do what they like. Classes may also define overloaded opAssign functions, which could potentially act as object conversion operators. Brad

Thanks. You explained that much better than I did. :) TZ
Apr 20 2005
prev sibling next sibling parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
"Ben Hinkle" <ben.hinkle gmail.com> wrote in message
news:d46v3g$1n7o$1 digitaldaemon.com...
 "TechnoZeus" <TechnoZeus PeoplePC.com> wrote in message
 news:d46tp4$1m37$1 digitaldaemon.com...
 I'm inviting anyone who wants to summarize their thoughts or comments on
 the proposed ":=" assignment opperator to do so as a reply to this post...
 to save Walter the time necessary to otherwise search for such comments.

What exactly is the proposed behavior? For instance what would it do for builtin types, pointers, arrays, structs, and classes? The post with [suggestion][Walter] in the subject mentions "assign by value" but that's too vague for me. For example how deep does the deep assignment go? I haven't looked at all the other posts in the thread but I'd be surprised if this is really the right way to address the problem. Actually now that I think of it - what is the problem? I assume it's that inside templates "=" assigns by value for value types and by reference for reference types, correct? Plus I skimmed a post or two about a problem that there is an asymmetry between "==" and "is" and assignment (which only has "="). About the template problem: I'd prefer to look into something like extending ".dup" to all types rather than invent a new operator. But I haven't thought about it really. About the asymmetry problem: D is designed to be practical so while it would be nice to have symmetry I wouldn't consider that a goal.

My understanding of the overal concensus is that := would be used to copy the contents of the source to the destination, but not copy the address of the source and not alter the address of the destination. Not everyone is in "full agreement" but this much does appear to be pretty consistantly agreed on. I didn't want to say too much in the post with [Walter] in the subject, because I thought it better if everyone had an equal opportunity to present their take on it, since the agreement was obviously not total and across the board. To answer your questions, here is my take on the aspects which you asked about... For basic data types, := would set the vaue of the item's data. For pointer types, := would set the location pointed to by the pointer's value. For array types, := would set the contents of the destination array or of the specified subset of the array in the case of a slice as the destination. In general, when you name an object, you specify the identity of that object by name. That identity is represented internally by a memory address. The := operator would not assign anything to that address, but would rather assign something to the contents pointed to by that address. I hope this helps to clarify what was meant. TechnoZeus
Apr 20 2005
prev sibling parent reply pragma <pragma_member pathlink.com> writes:
In article <d46v3g$1n7o$1 digitaldaemon.com>, Ben Hinkle says...
About the template problem: I'd prefer to look into something like extending 
".dup" to all types rather than invent a new operator. 

Ben, thank you. You took the words right out of my mouth. :) For classes, there's no need to make this a formal 'operator'. It could merely be added to Object as a shallow copy (return this;) and then overridden in any class where it's needed. So really, all that's needed is a 'dup' property for scalars. The rest is up to the developer. class Foobar{ public Foobar dup(){ return this; // or a copy } } void main(){ Foobar a,b; a = new Foobar(); b = a.dup; // custom ('deep') copy int c,d; c = d.dup; // value-copy: allowed for consistency int[] e,f e = f.dup; // old hat } The above folds into templates, extremely well: template valueOf(T){ T valueOf(T x){ return x.dup; } } .. where 'T' can be, well, anything. I'll add that the above is also *impossible* with ':=' and would require a temporary varible to work. Thus, it would be less flexible (and probably useful IMO). There's absolutely no need for an additional operator like ':='. - EricAnderton at yahoo
Apr 21 2005
next sibling parent reply Vladimir <kv11111 mail.ru> writes:
pragma wrote:

 In article <d46v3g$1n7o$1 digitaldaemon.com>, Ben Hinkle says...
About the template problem: I'd prefer to look into something like
extending ".dup" to all types rather than invent a new operator.

Ben, thank you. You took the words right out of my mouth. :) For classes, there's no need to make this a formal 'operator'. It could merely be added to Object as a shallow copy (return this;) and then overridden in any class where it's needed. So really, all that's needed is a 'dup' property for scalars. The rest is up to the developer. class Foobar{ public Foobar dup(){ return this; // or a copy } } void main(){ Foobar a,b; a = new Foobar(); b = a.dup; // custom ('deep') copy int c,d; c = d.dup; // value-copy: allowed for consistency int[] e,f e = f.dup; // old hat } The above folds into templates, extremely well: template valueOf(T){ T valueOf(T x){ return x.dup; } } .. where 'T' can be, well, anything. I'll add that the above is also *impossible* with ':=' and would require a temporary varible to work. Thus, it would be less flexible (and probably useful IMO). There's absolutely no need for an additional operator like ':='.

be forgotten, especially when one tries to convert non-template function to template. May be we can add ':' unary operator which in expression :a works exactly like a.dup ? So a=b.dup will look as a = :b or even a =: b. When returning from function this will look like { return :a; }. -- Vladimir
Apr 21 2005
next sibling parent reply pragma <pragma_member pathlink.com> writes:
In article <d48gt8$8ao$1 digitaldaemon.com>, Vladimir says...
May be we can add ':' unary operator which in expression :a works exactly
like a.dup ? So a=b.dup will look as a = :b or even a =: b. When returning
from function this will look like { return :a; }.

The only wart here is that you'll run into small problems with ':' when evaluating the ternary '?' operator: foo() ? bar() : a; // what was meant here? (value-of or ternary else) .. but that's strictly a matter of operator precedence. I for one, don't find it as readable. Not that I think it's a good idea, but you could use something like ' ' to mean 'value-of' (which would be akin to '&' meaning 'address-of'). { return a; } This isn't too bad, but it still lands us in "create a new operator territory". I still think .dup() is the way to go. -EricAnderton at yahoo
Apr 21 2005
parent reply Vladimir <kv11111 mail.ru> writes:
pragma wrote:
 In article <d48gt8$8ao$1 digitaldaemon.com>, Vladimir says...
May be we can add ':' unary operator which in expression :a works exactly
like a.dup ? So a=b.dup will look as a = :b or even a =: b. When returning
from function this will look like { return :a; }.

The only wart here is that you'll run into small problems with ':' when evaluating the ternary '?' operator: foo() ? bar() : a; // what was meant here? (value-of or ternary else) .. but that's strictly a matter of operator precedence. I for one, don't find it as readable. Not that I think it's a good idea, but you could use something like ' ' to mean 'value-of' (which would be akin to '&' meaning 'address-of'). { return a; } This isn't too bad, but it still lands us in "create a new operator territory".

fundamental data type" and "create a new operator" ?
 
 I still think .dup() is the way to go.

The only thing is that having operator it's too big tempting to allow T for creating class-value-type, which Walter will never accept, wont he ? :-) Anyway, if implemented, .dup() or := or would be very useful feature. -- Vladimir
Apr 21 2005
parent reply pragma <pragma_member pathlink.com> writes:
In article <d48pet$g4d$1 digitaldaemon.com>, Vladimir says...
 Not that I think it's a good idea, but you could use something like ' ' to
 mean 'value-of' (which would be akin to '&' meaning 'address-of').
 
 { return  a; }

 This isn't too bad, but it still lands us in "create a new operator
 territory".

fundamental data type" and "create a new operator" ?

Largely, the compiler impact is the biggest difference; a universal dup() property won't require anything new in the lexer and will likely be easily attached to the property evaluation bits already present. Adding a ':=' operator requires changes to the lexer, and a expression handling branch, with quirks and rules all its own. IMO, adding ':=' would be much more work to do, and not worth it since D has already (partially) sovled the problem. There is a smaller impact to D's grammar is a close second as ':=' is somewhat ambiguous when applied to certain cases; I'm welcome to be wrong about that. Regardless, .dup() is wholly unambiguous and meshes well with the present design.
 
 I still think .dup() is the way to go.

The only thing is that having operator it's too big tempting to allow T for creating class-value-type, which Walter will never accept, wont he ? :-)

Probably not. Again, I'd be willing to bet that extending .dup to everything would be cake to implement by comparison. - EricAnderton at yahoo
Apr 21 2005
next sibling parent reply "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
As it turns out, the .dup member function returns a reference, rather than a
value (at least in arrays, as I have tested it), and so does not qualify as a
substitute for directly working the a value rather than a reference.  The :=
reference operator is still needed.

TZ

"pragma" <pragma_member pathlink.com> wrote in message
news:d48rjc$ibp$1 digitaldaemon.com...
 In article <d48pet$g4d$1 digitaldaemon.com>, Vladimir says...
 Not that I think it's a good idea, but you could use something like ' ' to
 mean 'value-of' (which would be akin to '&' meaning 'address-of').

 { return  a; }

 This isn't too bad, but it still lands us in "create a new operator
 territory".

fundamental data type" and "create a new operator" ?

Largely, the compiler impact is the biggest difference; a universal dup() property won't require anything new in the lexer and will likely be easily attached to the property evaluation bits already present. Adding a ':=' operator requires changes to the lexer, and a expression handling branch, with quirks and rules all its own. IMO, adding ':=' would be much more work to do, and not worth it since D has already (partially) sovled the problem. There is a smaller impact to D's grammar is a close second as ':=' is somewhat ambiguous when applied to certain cases; I'm welcome to be wrong about that. Regardless, .dup() is wholly unambiguous and meshes well with the present design.
 I still think .dup() is the way to go.

The only thing is that having operator it's too big tempting to allow T for creating class-value-type, which Walter will never accept, wont he ? :-)

Probably not. Again, I'd be willing to bet that extending .dup to everything would be cake to implement by comparison. - EricAnderton at yahoo

Apr 22 2005
parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
oops... brain thought one thing, and hands typed another.

that last line should have read...

The := value assignment operator is still needed.

TZ

"TechnoZeus" <TechnoZeus PeoplePC.com> wrote in message
news:d4adkr$21p6$1 digitaldaemon.com...
 As it turns out, the .dup member function returns a reference, rather than a
value (at least in arrays, as I have tested it), and so does not qualify as a
substitute for directly working the a value rather than a reference.  The :=
reference operator is still needed.

 TZ

 "pragma" <pragma_member pathlink.com> wrote in message
news:d48rjc$ibp$1 digitaldaemon.com...
 In article <d48pet$g4d$1 digitaldaemon.com>, Vladimir says...
 Not that I think it's a good idea, but you could use something like ' ' to
 mean 'value-of' (which would be akin to '&' meaning 'address-of').

 { return  a; }

 This isn't too bad, but it still lands us in "create a new operator
 territory".

fundamental data type" and "create a new operator" ?

Largely, the compiler impact is the biggest difference; a universal dup() property won't require anything new in the lexer and will likely be easily attached to the property evaluation bits already present. Adding a ':=' operator requires changes to the lexer, and a expression handling branch, with quirks and rules all its own. IMO, adding ':=' would be much more work to do, and not worth it since D has already (partially) sovled the problem. There is a smaller impact to D's grammar is a close second as ':=' is somewhat ambiguous when applied to certain cases; I'm welcome to be wrong about that. Regardless, .dup() is wholly unambiguous and meshes well with the present design.
 I still think .dup() is the way to go.

The only thing is that having operator it's too big tempting to allow T for creating class-value-type, which Walter will never accept, wont he ? :-)

Probably not. Again, I'd be willing to bet that extending .dup to everything would be cake to implement by comparison. - EricAnderton at yahoo


Apr 22 2005
prev sibling parent reply Vladimir <kv11111 mail.ru> writes:
Content-Type: text/plain; charset=koi8-r
Content-Transfer-Encoding: 8Bit

pragma wrote:

 In article <d48pet$g4d$1 digitaldaemon.com>, Vladimir says...
 Not that I think it's a good idea, but you could use something like ' '
 to mean 'value-of' (which would be akin to '&' meaning 'address-of').
 
 { return  a; }

 This isn't too bad, but it still lands us in "create a new operator
 territory".

fundamental data type" and "create a new operator" ?

Largely, the compiler impact is the biggest difference; a universal dup() property won't require anything new in the lexer and will likely be easily attached to the property evaluation bits already present. Adding a ':=' operator requires changes to the lexer, and a expression handling branch, with quirks and rules all its own.

discussed above ' ' operator, and it takes me about one hour. I've never seen gdc sources before, so I belive for Walter it takes not more than five minutes. Adding ':=' will be more difficult, but I like challenges.
 IMO, adding ':=' would be much more work to 
 do, and not worth it since D has already (partially) sovled the problem.

 
 There is a smaller impact to D's grammar is a close second as ':=' is
 somewhat ambiguous when applied to certain cases; I'm welcome to be wrong
 about that. Regardless, .dup() is wholly unambiguous and meshes well with
 the present design.
 
 
 I still think .dup() is the way to go.

The only thing is that having operator it's too big tempting to allow T for creating class-value-type, which Walter will never accept, wont he ? :-)

Probably not. Again, I'd be willing to bet that extending .dup to everything would be cake to implement by comparison. - EricAnderton at yahoo

-- Vladimir
Apr 22 2005
parent reply Brad Beveridge <brad somewhere.net> writes:
Vladimir - can you please explain the new behaviour of your patch?
 From looking at the patch, it appears that when you type
 object it gets translated into object.opValue() - is this correct?
Does the   operator handle built-in types?

I think this is great work, now if we could just figure out a way to 
convert from one type to another, such as
Foo a = new Foo();
Bar b = new Bar();
b := a;

then most issues raised in this discussion would be solved (I think)

Brad
Apr 22 2005
next sibling parent reply Vladimir <kv11111 mail.ru> writes:
Brad Beveridge wrote:

 Vladimir - can you please explain the new behaviour of your patch?
  From looking at the patch, it appears that when you type
  object it gets translated into object.opValue() - is this correct?

But may be we need some default behavior here, such as recursively apply for all members stopping at built-in types.
 Does the   operator handle built-in types?

 I think this is great work, now if we could just figure out a way to
 convert from one type to another, such as
 Foo a = new Foo();
 Bar b = new Bar();
 b := a;

 then most issues raised in this discussion would be solved (I think)

It is not in D trunk and may be never get there. It's just my test how can it be done.
 Brad

-- Vladimir
Apr 22 2005
next sibling parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
That's important too.  :)  Much appriated, of course.

TZ

"Vladimir" <kv11111 mail.ru> wrote in message
news:d4bsfo$9j3$1 digitaldaemon.com...
 Brad Beveridge wrote:

 Vladimir - can you please explain the new behaviour of your patch?
  From looking at the patch, it appears that when you type
  object it gets translated into object.opValue() - is this correct?

But may be we need some default behavior here, such as recursively apply for all members stopping at built-in types.
 Does the   operator handle built-in types?

 I think this is great work, now if we could just figure out a way to
 convert from one type to another, such as
 Foo a = new Foo();
 Bar b = new Bar();
 b := a;

 then most issues raised in this discussion would be solved (I think)

It is not in D trunk and may be never get there. It's just my test how can it be done.
 Brad

-- Vladimir

Apr 23 2005
prev sibling parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
"Vladimir" <kv11111 mail.ru> wrote in message
news:d4bsfo$9j3$1 digitaldaemon.com...
 Brad Beveridge wrote:

 It's just my test how can it be done.

 -- 
           Vladimir

Sorry. I should snipped the quote. What I meant to say was... testing how it can be done is important. Thanks for doing that. It's very much appreciated. TZ
Apr 23 2005
prev sibling parent reply Derek Parnell <derek psych.ward> writes:
On Sat, 23 Apr 2005 08:35:18 +1200, Brad Beveridge wrote:

 Vladimir - can you please explain the new behaviour of your patch?
  From looking at the patch, it appears that when you type
  object it gets translated into object.opValue() - is this correct?
 Does the   operator handle built-in types?
 
 I think this is great work, now if we could just figure out a way to 
 convert from one type to another, such as
 Foo a = new Foo();
 Bar b = new Bar();
 b := a;
 
 then most issues raised in this discussion would be solved (I think)

This ' ' proposal is the one that I'm liking the most so far. In other words use '&' to get something's RAM address, and use ' ' to get something's value. For things that support methods, the ' ' could translate to a call to the things opValue() method. For things that do not support methods, it would invoke opValue_r() if defined otherwise, its identical to the current D behaviour for casting. Of course, if the undocumented syntax relating to arrays is propagated to all types (see last example below), we could really have a useful programming construct. Foo a = new Foo(); Bar b = new Bar(); int c; real d; char[] e; b = a; // b.opValue(a); a = b; // a.opValue(b); c = b; // b.opValue_r(inout c); c = d; // c = cast(int)d; a = d; // a.opValue(d); e = a; // a.opValue_r(inout e); d = e; // d = opValue(in d, e); This idea would work for all things making it suitable for template usage too. -- Derek Parnell Melbourne, Australia 23/04/2005 10:27:19 AM
Apr 22 2005
next sibling parent reply Brad Beveridge <brad somewhere.net> writes:
Derek Parnell wrote:
 On Sat, 23 Apr 2005 08:35:18 +1200, Brad Beveridge wrote:
 
 
Vladimir - can you please explain the new behaviour of your patch?
 From looking at the patch, it appears that when you type
 object it gets translated into object.opValue() - is this correct?
Does the   operator handle built-in types?

I think this is great work, now if we could just figure out a way to 
convert from one type to another, such as
Foo a = new Foo();
Bar b = new Bar();
b := a;

then most issues raised in this discussion would be solved (I think)

This ' ' proposal is the one that I'm liking the most so far. In other words use '&' to get something's RAM address, and use ' ' to get something's value. For things that support methods, the ' ' could translate to a call to the things opValue() method. For things that do not support methods, it would invoke opValue_r() if defined otherwise, its identical to the current D behaviour for casting. Of course, if the undocumented syntax relating to arrays is propagated to all types (see last example below), we could really have a useful programming construct. Foo a = new Foo(); Bar b = new Bar(); int c; real d; char[] e; b = a; // b.opValue(a); a = b; // a.opValue(b); c = b; // b.opValue_r(inout c); c = d; // c = cast(int)d; a = d; // a.opValue(d); e = a; // a.opValue_r(inout e); d = e; // d = opValue(in d, e); This idea would work for all things making it suitable for template usage too.

opValue_r() - at least as I understand it. Ie, this suffers the same problem that the cast operator does - because it is unary there is no notion of the LHS. Is it possible to have an operator that is both unary and binary - depending on context? I can't think how. Brad
Apr 22 2005
next sibling parent Brad Beveridge <brad somewhere.net> writes:
 The   operator is currently unary, so there really is no notion of 
 opValue_r() - at least as I understand it.  Ie, this suffers the same 
 problem that the cast operator does - because it is unary there is no 
 notion of the LHS.
 Is it possible to have an operator that is both unary and binary - 
 depending on context?  I can't think how.
 
 Brad

operator, which will call opValue with a parameter a -- calls a.opValue() a = b -- calls a.opValue(b), or b.opValue_r(a) Since if you think about it, a conversion must create a new object. Brad
Apr 22 2005
prev sibling parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
Any binary operator could be made to act unary,
as long as the operator isn't restricted to being commutative.

As a crude example,
int a;
int b;
a + -b; // add negative b to a.
a - b; // subtract b from a.
a + (0-b); Much like "a + -b;" the subtraction doesn't need to know about "a"
in this case.

TZ

"Brad Beveridge" <brad somewhere.net> wrote in message
news:d4c64h$goe$1 digitaldaemon.com...
 Derek Parnell wrote:
 On Sat, 23 Apr 2005 08:35:18 +1200, Brad Beveridge wrote:


Vladimir - can you please explain the new behaviour of your patch?
 From looking at the patch, it appears that when you type
 object it gets translated into object.opValue() - is this correct?
Does the   operator handle built-in types?

I think this is great work, now if we could just figure out a way to
convert from one type to another, such as
Foo a = new Foo();
Bar b = new Bar();
b := a;

then most issues raised in this discussion would be solved (I think)

This ' ' proposal is the one that I'm liking the most so far. In other words use '&' to get something's RAM address, and use ' ' to get something's value. For things that support methods, the ' ' could translate to a call to the things opValue() method. For things that do not support methods, it would invoke opValue_r() if defined otherwise, its identical to the current D behaviour for casting. Of course, if the undocumented syntax relating to arrays is propagated to all types (see last example below), we could really have a useful programming construct. Foo a = new Foo(); Bar b = new Bar(); int c; real d; char[] e; b = a; // b.opValue(a); a = b; // a.opValue(b); c = b; // b.opValue_r(inout c); c = d; // c = cast(int)d; a = d; // a.opValue(d); e = a; // a.opValue_r(inout e); d = e; // d = opValue(in d, e); This idea would work for all things making it suitable for template usage too.

opValue_r() - at least as I understand it. Ie, this suffers the same problem that the cast operator does - because it is unary there is no notion of the LHS. Is it possible to have an operator that is both unary and binary - depending on context? I can't think how. Brad

Apr 23 2005
prev sibling parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
Ironically, since the " " symbol is usually pronounced "at" (in English at
least) it would have been a nice choice for an address operator, to tell where
something is at.  Hehe.  Oh well... too late to change history.  We can get
used to it.  :)

TZ

"Derek Parnell" <derek psych.ward> wrote in message
news:pqibzzcik9ez$.1nw19ysr1xxya$.dlg 40tude.net...
 On Sat, 23 Apr 2005 08:35:18 +1200, Brad Beveridge wrote:

 Vladimir - can you please explain the new behaviour of your patch?
  From looking at the patch, it appears that when you type
  object it gets translated into object.opValue() - is this correct?
 Does the   operator handle built-in types?

 I think this is great work, now if we could just figure out a way to
 convert from one type to another, such as
 Foo a = new Foo();
 Bar b = new Bar();
 b := a;

 then most issues raised in this discussion would be solved (I think)

This ' ' proposal is the one that I'm liking the most so far. In other words use '&' to get something's RAM address, and use ' ' to get something's value. For things that support methods, the ' ' could translate to a call to the things opValue() method. For things that do not support methods, it would invoke opValue_r() if defined otherwise, its identical to the current D behaviour for casting. Of course, if the undocumented syntax relating to arrays is propagated to all types (see last example below), we could really have a useful programming construct. Foo a = new Foo(); Bar b = new Bar(); int c; real d; char[] e; b = a; // b.opValue(a); a = b; // a.opValue(b); c = b; // b.opValue_r(inout c); c = d; // c = cast(int)d; a = d; // a.opValue(d); e = a; // a.opValue_r(inout e); d = e; // d = opValue(in d, e); This idea would work for all things making it suitable for template usage too. -- Derek Parnell Melbourne, Australia 23/04/2005 10:27:19 AM

Apr 23 2005
prev sibling parent reply "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
"Vladimir" <kv11111 mail.ru> wrote in message
news:d48gt8$8ao$1 digitaldaemon.com...
 pragma wrote:

 In article <d46v3g$1n7o$1 digitaldaemon.com>, Ben Hinkle says...
About the template problem: I'd prefer to look into something like
extending ".dup" to all types rather than invent a new operator.

Ben, thank you. You took the words right out of my mouth. :) For classes, there's no need to make this a formal 'operator'. It could merely be added to Object as a shallow copy (return this;) and then overridden in any class where it's needed. So really, all that's needed is a 'dup' property for scalars. The rest is up to the developer. class Foobar{ public Foobar dup(){ return this; // or a copy } } void main(){ Foobar a,b; a = new Foobar(); b = a.dup; // custom ('deep') copy int c,d; c = d.dup; // value-copy: allowed for consistency int[] e,f e = f.dup; // old hat } The above folds into templates, extremely well: template valueOf(T){ T valueOf(T x){ return x.dup; } } .. where 'T' can be, well, anything. I'll add that the above is also *impossible* with ':=' and would require a temporary varible to work. Thus, it would be less flexible (and probably useful IMO). There's absolutely no need for an additional operator like ':='.

be forgotten, especially when one tries to convert non-template function to template. May be we can add ':' unary operator which in expression :a works exactly like a.dup ? So a=b.dup will look as a = :b or even a =: b. When returning from function this will look like { return :a; }. -- Vladimir

Correct me if I'm mistaken, but I think what you are saying only takes reference types into account. The idea here is to get away from the risk of code failing to work when value types and reference types inevitably get confused. There is, for example, not much sense to the following code... int a = 5.dup; int b; int c; b = a.dup + 7.dup; c = b.dup; Of course, this is an extreme case, but it is meant to illustrate a point. 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. TZ
Apr 21 2005
next sibling parent reply pragma <pragma_member pathlink.com> writes:
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"? b = (a+7).opValue; .. or "take the actual value of all the distinct portions of the lvalue"? b = a.opValue + 7.opValue; Which is correct? Also, keep in mind, that with either interpretation, will limit its percieved utility: T a,b,c,d; a := b + c + d; To obtain the opvalue of just one of b,c or d, i need to use more than one expression; regardless of the actual interpretation of ':='. To side-step the limitations of the operator. This is in sharp contrast to operators like good ol' '=' or even '&', which are much more explicit. With an explicit syntax like '.dup' there's no question as to what's going on. - EricAnderton at yahoo
Apr 21 2005
next sibling parent reply pragma <pragma_member pathlink.com> writes:
I should've double-checked before posting.

by 'lvalue', I actually mean 'rvalue'.  Sorry for the confusion.

-EricAnderton at yahoo

In article <d48nr3$ejr$1 digitaldaemon.com>, pragma says...
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"? b = (a+7).opValue; .. or "take the actual value of all the distinct portions of the lvalue"? b = a.opValue + 7.opValue; Which is correct? Also, keep in mind, that with either interpretation, will limit its percieved utility: T a,b,c,d; a := b + c + d; To obtain the opvalue of just one of b,c or d, i need to use more than one expression; regardless of the actual interpretation of ':='. To side-step the limitations of the operator. This is in sharp contrast to operators like good ol' '=' or even '&', which are much more explicit. With an explicit syntax like '.dup' there's no question as to what's going on. - EricAnderton at yahoo

Apr 21 2005
parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
Actually, it's not ambiguous at all.  At least, not to me... and I'm guessing
not to other people who see the advantages of a := value assignment operator. 
There is a clear distinction between working with values and working with
identities.  If you interpret "a+7" as an identity operation, then that
interpretation obviously can't be assigned using a value assignment operator. 
If you interpret it as a value operation, then the results would be a value. 
You don't need to look for the value stored at the location pointed to by the
identity referenced to specify the value.  That's recursive, and serves only to
cause an invinite loop.

b := a+7;

would mean that the value "7" is added to the value stored in "a" and then the
value of b is set to the resulting value.  No ambiguity.  That's the idea.

TZ

"pragma" <pragma_member pathlink.com> wrote in message
news:d48osb$fgg$1 digitaldaemon.com...
 I should've double-checked before posting.

 by 'lvalue', I actually mean 'rvalue'.  Sorry for the confusion.

 -EricAnderton at yahoo

 In article <d48nr3$ejr$1 digitaldaemon.com>, pragma says...
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"? b = (a+7).opValue; .. or "take the actual value of all the distinct portions of the lvalue"? b = a.opValue + 7.opValue; Which is correct? Also, keep in mind, that with either interpretation, will limit its percieved utility: T a,b,c,d; a := b + c + d; To obtain the opvalue of just one of b,c or d, i need to use more than one expression; regardless of the actual interpretation of ':='. To side-step the limitations of the operator. This is in sharp contrast to operators like good ol' '=' or even '&', which are much more explicit. With an explicit syntax like '.dup' there's no question as to what's going on. - EricAnderton at yahoo


Apr 22 2005
prev sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
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
Apr 21 2005
parent reply Brad Beveridge <brad somewhere.net> writes:
 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
Apr 21 2005
parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
Yep.

TZ

"Brad Beveridge" <brad somewhere.net> wrote in message
news:d494bj$qho$1 digitaldaemon.com...
 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

Apr 22 2005
prev sibling parent reply xs0 <xs0 xs0.com> writes:
 Correct me if I'm mistaken, but I think what you are saying only takes
reference types into account.  The idea here is to get away from the risk of
code failing to work when value types and reference types inevitably get
confused.
 
 There is, for example, not much sense to the following code...
 
 int a = 5.dup;
 int b;
 int c;
 b = a.dup + 7.dup;
 c = b.dup;
 
 Of course, this is an extreme case, but it is meant to illustrate a point.
 
 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.

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. Just allocating memory without calling the constructor is not an option at all, because the opValue (or whatever) may depend on the objects state being initialized... Furthermore, if you do a:=b+c, you needlessly create a new object (the result of b+c), so it would be very inefficient. Finally, if (a is b), modifying either with := would also modify the other, so you just move the problem to other cases. In other words, a:=c+d modifies b as well, and it's a=c+d that doesn't. IMO, all of these mean that := will not actually help with the value_types/reference_types divide, but will instead only shift the problems to other cases. I think the best option is to either - write two versions of templates, one specialized on Object, or - use the a=b+0 idiom and implement opAdd on all relevant classes xs0
Apr 21 2005
next sibling parent reply Vladimir <kv11111 mail.ru> writes:
xs0 wrote:

 
 Correct me if I'm mistaken, but I think what you are saying only takes
 reference types into account.  The idea here is to get away from the risk
 of code failing to work when value types and reference types inevitably
 get confused.
 
 There is, for example, not much sense to the following code...
 
 int a = 5.dup;
 int b;
 int c;
 b = a.dup + 7.dup;
 c = b.dup;
 
 Of course, this is an extreme case, but it is meant to illustrate a
 point.
 
 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.

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.

digitalmars.D/22165
 Just allocating memory without calling the constructor is not an option
 at all, because the opValue (or whatever) may depend on the objects
 state being initialized...
 
 Furthermore, if you do a:=b+c, you needlessly create a new object (the
 result of b+c), so it would be very inefficient.
 
 Finally, if (a is b), modifying either with := would also modify the
 other, so you just move the problem to other cases. In other words,
 a:=c+d modifies b as well, and it's a=c+d that doesn't.
 
 IMO, all of these mean that := will not actually help with the
 value_types/reference_types divide, but will instead only shift the
 problems to other cases.
 
 I think the best option is to either
 - write two versions of templates, one specialized on Object, or
 - use the a=b+0 idiom and implement opAdd on all relevant classes
 
 
 xs0

-- Vladimir
Apr 21 2005
parent reply xs0 <xs0 xs0.com> writes:
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: 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
Apr 21 2005
next sibling parent Vladimir <kv11111 mail.ru> writes:
xs0 wrote:

 
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: 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

Possible solution is to allow .init property to return new instance of class: class A { static A init() { // return new A object with reasonable state return new A(0,0); // default is return null; } } so for now A a,b; a == b - true a is b - false
 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 =.
 
 

-- Vladimir
Apr 22 2005
prev sibling parent reply "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
No, if the variable is uninitialized and a value is assigned, then assigning
that value "is" the initialization.  You don't just throw a copy of the value
where-ever the unitinitialized reference type happens to be pointing to. an
implicit "new" would alocate the space for it.

The idea is to make a value assignment operator that works with both value and
reference types, not to make one that works with value types and fails to
accomodate reference types.  That wouldn't be any improvement over what we have
now.

TZ

"xs0" <xs0 xs0.com> wrote in message news:d49aeq$1047$1 digitaldaemon.com...
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: 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

Apr 22 2005
parent reply xs0 <xs0 xs0.com> writes:
TechnoZeus wrote:
 No, if the variable is uninitialized and a value is assigned, then
 assigning that value "is" the initialization. 

How exactly do you expect the compiler to know what is and what isn't the value of an object? For example, if the object is just a wrapper for another object, the other object is the value, so it won't help to shallow-copy the original. OTOH, doing a deep-copy by default sucks, because in many cases it's not needed (w/ unmodifiable objects), and/or not desired (you don't want to have 25000 connections to a database open). So, the only sensible option is to make the object provide its own duplicate. You can already do that. OK, so you have two versions of the template. If you don't want two versions of the main template, write an assign template, specialize it for Objects and arrays, and use wherever you'd use a=b. Again, note that this issue only applies to simple assignments "a=b". In the case of expression "a=b+c", a new object will be constructed as-is, so there is no need for another operator.
 You don't just throw a
 copy of the value where-ever the unitinitialized reference type happens
 to be pointing to. an implicit "new" would alocate the space for it.

You'd always allocate a new object, even if it was already allocated?
 The idea is to make a value assignment operator that works with both
 value and reference types, not to make one that works with value types
 and fails to accomodate reference types. That wouldn't be any
 improvement over what we have now.

Duh! xs0
 
 "xs0" <xs0 xs0.com> wrote in message news:d49aeq$1047$1 digitaldaemon.com...
 
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: 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


Apr 25 2005
parent reply "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
"xs0" <xs0 xs0.com> wrote in message news:d4ilv1$1m84$1 digitaldaemon.com...
 TechnoZeus wrote:

 How exactly do you expect the compiler to know what is and what isn't
 the value of an object?

 xs0

I don't expect the compiler to know the difference at that level. Right now, it doesn't know the difference at "any" level. It simply copies identities or values depending on what it is dealing with. All I'm asking for is a way to remove the "depending on what it is dealing with" and replace it with "depending on what it was asked to do" so that it will if the value of an item is an address, or a wrapper, or whatever, we can compare or assign that "value" without having to first establish what syntax we have to use based on what the value is contained in. In other words, a:=b should "always" mean... copy the contents of "b" into "a" no matter whther "a" and "b" are classes, integers, arrays, or what ever, as long as it is possible to change the value of "a" and as long as the data contained in "b" is capable of being stored in "a" ... period. TZ
Apr 27 2005
parent reply xs0 <xs0 xs0.com> writes:
TechnoZeus wrote:
 "xs0" <xs0 xs0.com> wrote in message news:d4ilv1$1m84$1 digitaldaemon.com...
 
TechnoZeus wrote:

How exactly do you expect the compiler to know what is and what isn't
the value of an object?

*snip*
xs0

I don't expect the compiler to know the difference at that level. Right now, it doesn't know the difference at "any" level. It simply copies identities or values depending on what it is dealing with.

No, it always copies the value. You just seem to think that the value of a reference is the object it's pointing to, not the reference itself.
 All I'm asking for is a way to remove the "depending on what it is 
 dealing with" and replace it with "depending on what it was asked 
 to do" 

OK then, how do you expect the compiler to know what it was asked to do? Again, you assume it is possible for the compiler to automatically know what _you_ consider a value.
 so that it will if the value of an item is an address, or a
  wrapper, or whatever, we can compare or assign that "value" without 
 having to first establish what syntax we have to use based on what 
 the value is contained in.

Again, the only reasonable way to do this is to let the object itself determine what its value is (in other words, to let you determine it). If you do that, you will still have to use different syntax, it will just be shifted elsewhere. int a:=b; // OK Object c:=d; // not OK, because c is null
 In other words, a:=b should "always" mean...  copy the contents of "b" into "a"
 no matter whther "a" and "b" are classes, integers, arrays, or what ever,
 as long as it is possible to change the value of "a" and as long as the
 data contained in "b" is capable of being stored in "a"  ... period.

See the above example for why you need to handle things differently in any case. Using dummy init values is a somewhat naive solution, and just copying bit-by-bit is only an option if both sides are of the exact same type, even if you disregard what a source of bugs it can be. I feel you don't realize that it's not possible to somehow magically treat globals, stack variables (locals) and heap variables (objects) all the same. Each have their specifics which you have to be aware of in order to use them correctly. Even a local int and a global int differ in important ways, and they're both ints. You're just so used to their differences (like their lifetime), you don't see it as an issue. xs0
Apr 28 2005
parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
"xs0" <xs0 xs0.com> wrote in message news:d4qt4a$unl$1 digitaldaemon.com...
 TechnoZeus wrote:
 "xs0" <xs0 xs0.com> wrote in message news:d4ilv1$1m84$1 digitaldaemon.com...

TechnoZeus wrote:

How exactly do you expect the compiler to know what is and what isn't
the value of an object?

*snip*
xs0

I don't expect the compiler to know the difference at that level. Right now, it doesn't know the difference at "any" level. It simply copies identities or values depending on what it is dealing with.

No, it always copies the value. You just seem to think that the value of a reference is the object it's pointing to, not the reference itself.
 All I'm asking for is a way to remove the "depending on what it is
 dealing with" and replace it with "depending on what it was asked
 to do"

OK then, how do you expect the compiler to know what it was asked to do? Again, you assume it is possible for the compiler to automatically know what _you_ consider a value.
 so that it will if the value of an item is an address, or a
  wrapper, or whatever, we can compare or assign that "value" without
 having to first establish what syntax we have to use based on what
 the value is contained in.

Again, the only reasonable way to do this is to let the object itself determine what its value is (in other words, to let you determine it). If you do that, you will still have to use different syntax, it will just be shifted elsewhere. int a:=b; // OK Object c:=d; // not OK, because c is null
 In other words, a:=b should "always" mean...  copy the contents of "b" into "a"
 no matter whther "a" and "b" are classes, integers, arrays, or what ever,
 as long as it is possible to change the value of "a" and as long as the
 data contained in "b" is capable of being stored in "a"  ... period.

See the above example for why you need to handle things differently in any case. Using dummy init values is a somewhat naive solution, and just copying bit-by-bit is only an option if both sides are of the exact same type, even if you disregard what a source of bugs it can be. I feel you don't realize that it's not possible to somehow magically treat globals, stack variables (locals) and heap variables (objects) all the same. Each have their specifics which you have to be aware of in order to use them correctly. Even a local int and a global int differ in important ways, and they're both ints. You're just so used to their differences (like their lifetime), you don't see it as an issue. xs0

I realize more than you are aparently capable of comprehending. What you are stating as imutable fact is actually implementation dependant. Unfortunatley, I don't know how it was implemented in D, but I know there is more than one way of looking at it, and more than one way of implementing it. In case you hadn't noticed, the compiler does know the difference between a reference type and a value type. Well... Obviously, either those who want the same thing I want are either the minority, or mostly quiet people... so I'm giving up. I've stated my case, and I'm getting insults for it rather than discussion. I have better things to do. Donald A. Kronos, PhD. - TechnoZeus
Apr 29 2005
prev sibling parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
"xs0" <xs0 xs0.com> wrote in message news:d48tfo$k26$1 digitaldaemon.com...
 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.

No, there's no problem with it at all. You're thinking in C. TZ
Apr 22 2005
prev sibling next sibling parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
"pragma" <pragma_member pathlink.com> wrote in message 
news:d48dib$57l$1 digitaldaemon.com...
 In article <d46v3g$1n7o$1 digitaldaemon.com>, Ben Hinkle says...
About the template problem: I'd prefer to look into something like 
extending
".dup" to all types rather than invent a new operator.

Ben, thank you. You took the words right out of my mouth. :) For classes, there's no need to make this a formal 'operator'. It could merely be added to Object as a shallow copy (return this;) and then overridden in any class where it's needed. So really, all that's needed is a 'dup' property for scalars. The rest is up to the developer.

One issue with .dup is that the expression x.dup calls the same thing if x is a struct or a ptr to a struct. Not that I'm complaining since I don't think the := does any better wrt pointers. In general I'm not optimistic about either := or .dup helping template programming by themselves. 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.
Apr 21 2005
next sibling parent reply Vladimir <kv11111 mail.ru> writes:
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: digitalmars.D/22137 Of course there are workarounds, but they are ugly and error-prone. 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. BTW in C++ this example can be _easily_ implemented. -- Vladimir
Apr 21 2005
parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
"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: 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>
Apr 21 2005
parent reply Brad Beveridge <brad somewhere.net> writes:
 
 Can you give a more complete example? I'm assume this happened to you for 
 real.
 

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
Apr 21 2005
parent "Ben Hinkle" <ben.hinkle gmail.com> writes:
"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.

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.
Apr 21 2005
prev sibling parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
:= wouldn't assign the value of a struct pointed to by it's right operand.  It
would assign the value of it's right operand.  Even if that operand is a
pointer, in which case it's value is the address of the location that it points
to.  Not the data stored at that location.

In other words, no it wouldn't have the same problem.

TZ

"Ben Hinkle" <bhinkle mathworks.com> wrote in message
news:d48sn8$jbq$1 digitaldaemon.com...
 "pragma" <pragma_member pathlink.com> wrote in message
 news:d48dib$57l$1 digitaldaemon.com...
 In article <d46v3g$1n7o$1 digitaldaemon.com>, Ben Hinkle says...
About the template problem: I'd prefer to look into something like
extending
".dup" to all types rather than invent a new operator.

Ben, thank you. You took the words right out of my mouth. :) For classes, there's no need to make this a formal 'operator'. It could merely be added to Object as a shallow copy (return this;) and then overridden in any class where it's needed. So really, all that's needed is a 'dup' property for scalars. The rest is up to the developer.

One issue with .dup is that the expression x.dup calls the same thing if x is a struct or a ptr to a struct. Not that I'm complaining since I don't think the := does any better wrt pointers. In general I'm not optimistic about either := or .dup helping template programming by themselves. 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.

Apr 22 2005
prev sibling parent "Regan Heath" <regan netwin.co.nz> writes:
On Thu, 21 Apr 2005 14:32:43 +0000 (UTC), pragma  
<pragma_member pathlink.com> wrote:
 In article <d46v3g$1n7o$1 digitaldaemon.com>, Ben Hinkle says...
 About the template problem: I'd prefer to look into something like  
 extending
 ".dup" to all types rather than invent a new operator.

Ben, thank you. You took the words right out of my mouth. :) For classes, there's no need to make this a formal 'operator'. It could merely be added to Object as a shallow copy (return this;) and then overridden in any class where it's needed. So really, all that's needed is a 'dup' property for scalars. The rest is up to the developer. class Foobar{ public Foobar dup(){ return this; // or a copy } } void main(){ Foobar a,b; a = new Foobar(); b = a.dup; // custom ('deep') copy int c,d; c = d.dup; // value-copy: allowed for consistency int[] e,f e = f.dup; // old hat } The above folds into templates, extremely well: template valueOf(T){ T valueOf(T x){ return x.dup; } } .. where 'T' can be, well, anything. I'll add that the above is also *impossible* with ':=' and would require a temporary varible to work. Thus, it would be less flexible (and probably useful IMO). There's absolutely no need for an additional operator like ':='.

Assuming .dup is added for intrinsics. However... Dereks original goal was to achieve this: class A {} class B {} A a = new A(); B b; b = a; i.e. construct b using a. The current proposed method is a copy constructor. But, as intrinsics have no constructors how do you write it generically? := solves that problem as well as the other which .dup can solve. Regan
Apr 21 2005
prev sibling parent reply Vladimir <kv11111 mail.ru> writes:
Content-Type: text/plain; charset=koi8-r
Content-Transfer-Encoding: 8Bit

Hello All !
Here is patch for gdc-0.10 implementing   and  = operators. This patch is
not intended for direct use, this is just my test how can it be done.

  is unary operator which currently:
  tries to overwrite expression as rvalue.opValue()
  returns rvalue for structs without opValue
  returns rvalue for arithmetic types
  fails to compile otherwise. 

 = is binary operator which currently:
  tries to overwrite expression as lvalue.opValueAssign(rvalue)
  overwrites expression as lvalue = rvalue for structs without opValueAssign
  overwrites expression as lvalue = rvalue for arithmetic types
  fails otherwise

' ' symbol means 'at' which emphasizes it's meaning in language:  a means
"get value *at* given location" and a = means "store value *at* given
location"

':=' is bad because D already has too many meanings for symbol ':'.

TODO:
  overwrite  array as array.dup (recursion here ?)
  overwrite a =array as a=array.dup (recursion here ?)
  decide what to do with pointers
    (possibilities:
       return rvalue
       return *rvalue
       return **...*rvalue (recursively))

Other ideas related to general template programming:

Allow static .init property for classes which will return new instance
of class for default variable initializing (by default return null).

For any type T allow T& and T  for reference (pointer?) and value types.
Multiple-applying should behave as: T&& equals T& and T   equals T . For
classes T& equals T, for structs and built-in types T  equals T. May be
this is too global change to be accepted, but it has a lot of benefits.

-- 
          Vladimir
Apr 25 2005
next sibling parent reply pragma <pragma_member pathlink.com> writes:
In article <d4ipf2$1poj$1 digitaldaemon.com>, Vladimir says...
--nextPart1356870.LVNHTvSSDs
Content-Type: text/plain; charset=koi8-r
Content-Transfer-Encoding: 8Bit

Hello All !
Here is patch for gdc-0.10 implementing   and  = operators. This patch is
not intended for direct use, this is just my test how can it be done.
 [snip]

Vlad, Thank you for taking the bazaar concept (or 'microfork' if you will) seriously and writing a reference implementation for this feature concept. I only hope that this stands as an example for how to more effectively communicate new language concepts from here on out (as has been discussed to death in this forum before). One question remains: what is the most effective way to apply such a patch for us *nix neophytes? - EricAnderton at yahoo
Apr 25 2005
next sibling parent =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
pragma wrote:

 One question remains: what is the most effective way to apply such a
 patch for us *nix neophytes?

Change to the "d" directory (where you unpacked GDC 0.10) and: patch -p1 -i d-opValue.patch Sometimes linefeeds will give you trouble... (ie. UNIX vs. DOS) Then you need to translate the Windows files to drop the '\r'. --anders PS. See also http://www.gnu.org/software/diffutils/manual/
Apr 25 2005
prev sibling parent Vladimir <kv11111 mail.ru> writes:
pragma wrote:
 Vlad,
 Thank you for taking the bazaar concept (or 'microfork' if you will)
 seriously
 and writing a reference implementation for this feature concept.  I only
 hope that this stands as an example for how to more effectively
 communicate new language concepts from here on out (as has been discussed
 to death in this forum before).

Actually while implementing this patch I've found some places where I was wrong in discussion and got some new ideas about how to do it better.
 One question remains: what is the most effective way to apply such a patch
 for us *nix neophytes?
 
 - EricAnderton at yahoo

-- Vladimir
Apr 25 2005
prev sibling parent Vladimir <kv11111 mail.ru> writes:
Vladimir wrote:
 TODO:
   overwrite  array as array.dup (recursion here ?)
   overwrite a =array as a=array.dup (recursion here ?)
   decide what to do with pointers
     (possibilities:
        return rvalue
        return *rvalue
        return **...*rvalue (recursively))

TODO: 1. By default (if not overloaded) recursively apply = to all members if lvalue and rvalue are of the same aggregate type (class, struct or array). Overloading are still need for (a) type conversion and (b) external resources handling. 2. By default (if not overloaded) try to rewrite a as { typeof(a) __t; __t = a; return __t; } This needs either a. Somehow redefine = for correct handling null lvalue (for example change overloading signature to: static T opAssignValue(inout T to, T from); so that inside function one can check if to is null react appropriate) b. Implement .init property for classes. Without this the following examples will cause seg-v: /* Can be solved by overloading opAssignValue for struct S */ class C { ... } struct S { C c; } S a, b; a = b; /* Can't be solved */ C[] array1 = new C[1]; C[] array2 = new C[1]; array2[0] = new C; array1 = array2; -- Vladimir
Apr 25 2005