Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2010-12

commutative operators

8 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

David Emerson

suppose I define an operator:

operator + (a: one_type; b: another_type) : one_type;

Is there any way to specify that it should be "commutative", so I don't have to additionally define the reverse:

operator + (a: another_type; b: one_type) : one_type;

Thanks
~David.

Honza
to David Emerson

2010/12/29 David Emerson :

Show quoted text 8 lines
suppose I define an operator: operator + (a: one_type; b: another_type) : one_type; Is there any way to specify that it should be "commutative", so I don't have to additionally define the reverse: operator + (a: another_type; b: one_type) : one_type;

IIRC you don't have to.

bflm freepascal-bits.blogspot.com
David Emerson
to Honza
Honza wrote 6 lines
2010/12/29 David Emerson : > suppose I define an operator: > > operator + (a: one_type; b: another_type) : one_type; > > Is there any way to specify that it should be "commutative", so I don't have

to

> additionally define the reverse: > > operator + (a: another_type; b: one_type) : one_type; IIRC you don't have to.
well... I do have to. I get "can't determine which overloaded function to call"
because I have a lot of similar-looking functions and := operators

it's not such a big deal, really.

Jetcheng Chu
to David Emerson: suppose I define an operator: operator + (a: one_type; b: another_type) : one_type; Is…

I think you need to make sure that `a' and `b' are in the same algebraic system before making the commutativity of the operator meaningful. Maybe you can merge `one_type' with `another_type' into a common type, or cast one to the other?

Earlier message 26 lines
----- Original Message ----- Subject: [fpc-pascal] commutative operators From: David Emerson To: FPC-Pascal users discussions Time: Wed, 29 Dec 2010 10:38:14 -0800 MUA: KMail/1.9.9 > suppose I define an operator: > > operator + (a: one_type; b: another_type) : one_type; > > Is there any way to specify that it should be "commutative", so I don't have to > additionally define the reverse: > > operator + (a: another_type; b: one_type) : one_type; > > Thanks > ~David. > > _______________________________________________ > fpc-pascal maillist - > http://lists.freepascal.org/mailman/listinfo/fpc-pascal -- Best Regards, J.-c. Chu
Honza
to David Emerson: to well... I do have to. I get "can't determine which overloaded function to call"…

2010/12/29 David Emerson :

Show quoted text 5 lines
On Wed 29 Dec 2010, Honza wrote: > IIRC you don't have to. well... I do have to. I get "can't determine which overloaded function to call" because I have a lot of similar-looking functions and := operators

You're right, I verified it just now. I didn't remembered it correctly.

FYI, bellow is the verification example used, later modified to compile successfully with trunk FPC. Introduction of the ':=' operators for T1 and T2 enabled the '+' operator commutativity.

program project1;
{$mode objfpc}{$H+}
type
  T1 = record
    Dummy: Boolean;
    Value: Integer;
  end;
  T2 = record
    Dummy: String;
    Value: Integer;
  end;
operator +(A: T1; B: T2): Integer;
begin
  Result := A.Value + B.Value;
end;
operator :=(X: T1): T2;
begin
  Result.Value := X.Value
end;
operator :=(X: T2): T1;
begin
  Result.Value := X.Value
end;
var
  V1: T1;
  V2: T2;
begin
  V1.Value := 2;
  V2.Value := 3;
  Writeln(V1 + V2, ' ', V2 + V1);
end.
bflm freepascal-bits.blogspot.com
Mark Morgan Lloyd
to Honza: 2010/12/29 David Emerson : You're right, I verified it just now. I didn't remembered it…
Honza wrote 10 lines
2010/12/29 David Emerson : > On Wed 29 Dec 2010, Honza wrote: >> IIRC you don't have to. > well... I do have to. I get "can't determine which overloaded function to call" > because I have a lot of similar-looking functions and := operators You're right, I verified it just now. I didn't remembered it correctly. FYI, bellow is the verification example used, later modified to compile successfully with trunk FPC. Introduction of the ':=' operators for T1 and T2 enabled the '+' operator commutativity.
Can I have a reality check on this please: in this context is the
overloaded := effectively an implicit cast as well as an explicit operator?
Is the availability of overloaded + and := operators necessary and
sufficient for += to work correctly?
Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]
David Emerson
to Mark Morgan Lloyd
Mark Morgan Lloyd wrote
Can I have a reality check on this please: in this context is the overloaded := effectively an implicit cast as well as an explicit operator?

looks like. Below is some sample code which illustrates the fact.

Is the availability of overloaded + and := operators necessary and sufficient for += to work correctly?

looks like. also illustrated below.

From the documentation, in reference to C-style += operators: "Remark: These constructions are just for typing convenience, they don’t generate different code."
In other words, a += b; is equivalent to a := a + b. So indeed, := and + are the requirements for +=
At least that's what I gather from the documentation, and the test program below.

Using fpc 2.4.2

Warning: for mathematical purists, these operators are absurd. However, they are illustrative. Enjoy.

{$mode objfpc}
type
  ta = record
    a : longint;
    end;
  tb = record
    b : longint;
    end;
operator := (a : ta) : tb;
  begin
    result.b := a.a+1;
  end;
operator := (b : tb) : ta;
  begin
    result.a := b.b+10;
  end;
operator + (a, aa : ta) : ta;
  begin
    result.a := a.a + aa.a;
  end;
operator + (a : ta; x : longint) : ta;
  begin
    result.a := a.a + x;
  end;
const
  spc = '  ###  ';
var
  a : ta;
  b : tb;
procedure write_before_op (true_for_a : boolean);
  begin
    if true_for_a
      then write ('a=', a.a, spc)
      else write ('b=', b.b, spc);
  end;
procedure write_after_op (s : string; true_for_a : boolean);
  begin
    write (s, spc);
    if true_for_a
      then writeln ('a=', a.a)
      else writeln ('b=', b.b);
  end;
begin
  a.a := 2;
  writeln ('a.a := 2');
  write_before_op (true);
  a += 1;
  write_after_op ('a += 1', true);  // 3
  write_before_op (true);
  a += a;
  write_after_op ('a += a', true);  // 6
  write_before_op (true);
  writeln ('tb(a).b=', tb(a).b);  // 7
  write_before_op (true);
  b := a;
  write_after_op ('b := a', false);  // 7
  write_before_op (false);
  a := b;
  write_after_op ('a := b', true);  // 17
  b.b := 1;
  writeln ('b.b := 1');
  write_before_op (false);
  a := b + b;  // each b must be typecast to ta, thus adding 10.
  write_after_op ('a := b + b', true);  // 22
  write_before_op (false);
  b := b + b;  // as above, but typecasting the result to tb adds another 1
  write_after_op ('b := b + b', false);  // 23
end.