View mode: basic / threaded / horizontal-split · Log in · Help
December 18, 2004
opAssign?
I'd like to have an opAssign() operator.  This would allow 
me to create new numeric types with syntax similar to 
built-in numeric types.  For example:

   struct clampf {
       private float value;
       opAssign(float assign) {
           assign = (assign =< 0) ? 0 : assign;
           value  = (assign >= 1) ? 1 : assign;
       }
       opAssign(clampf assign) {
           opAssign(assign.value);
       }
       // additional operators, eg. opAdd() etc.
   }

   clampf r, g, b;
   r = 0.5; // r.value == 0.5;
   g = r;   // g.value == 0.5;
   b = 2.f; // b.value == 1.0;

Then I could avoid clamping floating point values all the 
time, because I would always know that clampf's are clamped, 
and I could use the normal built-in type syntax.  It would 
also be handy to have implicit return functions, eg.:

   struct clampf {
       // ... see above
       float retFloat() {
           return value;
       }
   }

To allow numeric use such as:

   float f;
   f = r; // f == 0.5 (ie. f = r.retFloat())

Further, if this were all template friendly, then I could 
easily make a variety of clamp types with different limits. 
Thoughts, comments?

Regards,
Garett
December 18, 2004
Re: opAssign?
This may be feasible for structs, but not for classes I think.

class A has member function:

A opAssign( A other ) {... ; return other;}


Now I type
A foo = new A();
A bar = new A();

foo = bar;

what happens?  Is foo now un-rebindable?

Garett Bass wrote:
> I'd like to have an opAssign() operator.  This would allow 
> me to create new numeric types with syntax similar to 
> built-in numeric types.  For example:
> 
>     struct clampf {
>         private float value;
>         opAssign(float assign) {
>             assign = (assign =< 0) ? 0 : assign;
>             value  = (assign >= 1) ? 1 : assign;
>         }
>         opAssign(clampf assign) {
>             opAssign(assign.value);
>         }
>         // additional operators, eg. opAdd() etc.
>     }
> 
>     clampf r, g, b;
>     r = 0.5; // r.value == 0.5;
>     g = r;   // g.value == 0.5;
>     b = 2.f; // b.value == 1.0;
> 
> Then I could avoid clamping floating point values all the 
> time, because I would always know that clampf's are clamped, 
> and I could use the normal built-in type syntax.  It would 
> also be handy to have implicit return functions, eg.:
> 
>     struct clampf {
>         // ... see above
>         float retFloat() {
>             return value;
>         }
>     }
> 
> To allow numeric use such as:
> 
>     float f;
>     f = r; // f == 0.5 (ie. f = r.retFloat())
> 
> Further, if this were all template friendly, then I could 
> easily make a variety of clamp types with different limits. 
> Thoughts, comments?
> 
> Regards,
> Garett
> 
>  
> 
>
December 18, 2004
Re: opAssign?
David,

   I see your point.  However, I still see the value of 
opAssign().  Let the usual reference assignment take place 
when there is no opAssign() defined, and let opAssign() do 
its intended business if it is defined.  Thus, defining 
opAssign() means "Objects of this type don't want to be 
rebound, they want to copy-on-assignment".

   What makes things really strange is if you allow static 
opAssign(), which would effectively allow foo to copy 
whatever static values were present in new A().  Does that 
make sense at all?  I suspect static opAssign() would be an 
error.  Are static operator functions always considered 
erroneous?

   I think the numeric syntax advantages make this 
appealing.  I always wondered why there is unsigned int, but 
no unsigned float.  Certainly a 0..1, or -1..1 number class 
can be very handy at times, and it sure would be nice to 
keep the bounds checking centralized without sacrificing 
normal numeric syntax.

Regards,
Garett


"David Medlock" <amedlock@nospam.org> wrote in message 
news:cq0aa0$krt$1@digitaldaemon.com...
> This may be feasible for structs, but not for classes I 
> think.
>
> class A has member function:
>
> A opAssign( A other ) {... ; return other;}
>
>
> Now I type
> A foo = new A();
> A bar = new A();
>
> foo = bar;
>
> what happens?  Is foo now un-rebindable?
December 18, 2004
Re: opAssign?
I clearly see the advantage of it, don't get me wrong.  I just like the
simple semantics of D and wouldn't want it to get too messy.

For things such as ranges(as you stated ) as well as Metrix/English 
measurement classes with auto conversions would be very nice.

As for static OpXXX() functions, I think they are ignored when you use 
the operators(since you don't have a this variable they wouldnt be very 
useful anyway).

Cheers,
-Ash

Garett Bass wrote:
> David,
> 
>     I see your point.  However, I still see the value of 
> opAssign().  Let the usual reference assignment take place 
> when there is no opAssign() defined, and let opAssign() do 
> its intended business if it is defined.  Thus, defining 
> opAssign() means "Objects of this type don't want to be 
> rebound, they want to copy-on-assignment".
> 
>     What makes things really strange is if you allow static 
> opAssign(), which would effectively allow foo to copy 
> whatever static values were present in new A().  Does that 
> make sense at all?  I suspect static opAssign() would be an 
> error.  Are static operator functions always considered 
> erroneous?
> 
>     I think the numeric syntax advantages make this 
> appealing.  I always wondered why there is unsigned int, but 
> no unsigned float.  Certainly a 0..1, or -1..1 number class 
> can be very handy at times, and it sure would be nice to 
> keep the bounds checking centralized without sacrificing 
> normal numeric syntax.
> 
> Regards,
> Garett
> 
> 
> "David Medlock" <amedlock@nospam.org> wrote in message 
> news:cq0aa0$krt$1@digitaldaemon.com...
> 
>>This may be feasible for structs, but not for classes I 
>>think.
>>
>>class A has member function:
>>
>>A opAssign( A other ) {... ; return other;}
>>
>>
>>Now I type
>>A foo = new A();
>>A bar = new A();
>>
>>foo = bar;
>>
>>what happens?  Is foo now un-rebindable?
> 
> 
>
December 18, 2004
Re: opAssign?
David,

   Thanks for your points.  I've decided to use opCast() 
and opCall() to acheive the desired effect.  I have to 
cast(float) to assign a clampf to a float, and a(0.5) to 
assign a float to a clampf, but that hardly seems 
unreasonable, and it makes certain the user knows that 
clampf is not just a float.  I'm happy with the result.

Regards,
Garett
December 18, 2004
Re: opAssign?
David Medlock wrote:
> This may be feasible for structs, but not for classes I think.
> 
> class A has member function:
> 
> A opAssign( A other ) {... ; return other;}
> 
> 
> Now I type
> A foo = new A();
> A bar = new A();
> 
> foo = bar;
> 
> what happens?  Is foo now un-rebindable?

This is rather an issue with the ambiguity of `=', being binding 
operator for object references and assignment operator for everything 
else (and equality operator in Pascal, eeks).

Perhaps we need to change the syntax for variable binding in a later 
iteration of D, to enable opAssign for class instances? foo := bar??

Another syntax for assignment is much more evil as it would need to 
apply to all other types to be really consistent?

Oh, I know nothing of this is going to happen to D, but let me dream :(
I will just write foo.opAssign(bar) in the meantime!

-ben
December 21, 2004
Re: opAssign?
Garett Bass wrote:
> David,
> 
>     I see your point.  However, I still see the value of 
> opAssign().  Let the usual reference assignment take place 
> when there is no opAssign() defined, and let opAssign() do 
> its intended business if it is defined.  Thus, defining 
> opAssign() means "Objects of this type don't want to be 
> rebound, they want to copy-on-assignment".

If you want C++, you (I guess) know where to find it.

Seriously, I'm not sure that overriding = to copy class objects would be 
useful or desirable.  A virtue of the current = operator is that it is 
consistently defined for everything (copy whatever its right operand 
represents, be it a value or a reference), and this is useful for 
generic programming.  If its semantics are changed for certain types, 
someone will try to use templates that expect the default behaviour, 
possibly leading to bugs that are hard to diagnose.

See also, if you haven't already

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

Of course, if you want to be able to make a copy of an object, you can 
always define a .dup property.

>     What makes things really strange is if you allow static 
> opAssign(), which would effectively allow foo to copy 
> whatever static values were present in new A().  Does that 
> make sense at all?  I suspect static opAssign() would be an 
> error.  Are static operator functions always considered 
> erroneous?

No.  They denote the operator applied to the struct/union/class name. 
So if we had opAssign, it would lead to

    class Qwert {
        static Qwert opAssign(int i) { ... }
    }

    void main() {
        Qwert = 42;
    }

if that makes sense.

For a more meaningful example (using opCall), see

http://www.digitalmars.com/drn-bin/wwwnews?D/25334

>     I think the numeric syntax advantages make this 
> appealing.  I always wondered why there is unsigned int, but 
> no unsigned float.  Certainly a 0..1, or -1..1 number class 
> can be very handy at times, and it sure would be nice to 
> keep the bounds checking centralized without sacrificing 
> normal numeric syntax.
<snip top of upside-down reply>

Hmm ... maybe.  Maybe someone else can provide a more detailed opinion....

Stewart.

-- 
My e-mail is valid but not my primary mailbox.  Please keep replies on 
on the 'group where everyone may benefit.
Top | Discussion index | About this forum | D home