[Lazarus] Passing properties as var paramatars (was: Delphi editor clone)
Hans-Peter Diettrich
DrDiettrich1 at aol.com
Sat Nov 7 14:24:14 CET 2009
Alexander Klenin schrieb:
>> The answer was that properties are meant to change the value on the object
>> immediately. Also a property setter can raise an exception, or additional
>> actions can take place or the value can be substituted....
>> All this wouldn't happen with a temp variable (or at best deferred).
>> Therefore the behaviour would not be according to the rules of properties
>
> I thought about that too. There are few counter-arguments here:
>
> Strictly speaking, properties are not *meant* to change anything
> neither immediately nor
> in any other way. Assigning to a property with the setter is just a
> procedure call,
> and I do not think there exist any specification requiring the setter
> to change anything.
>
> So it is important to understand that we are dealing here with "common
> sense" and "usual expectations",
> not with any formal requirement.
>
> Now the question is, given the code:
> -----
> type T = class
> ...
> property P: Integer read GetP write SetP;
> end;
>
> procedure MyInc2(var a: Integer); begin a := a + 1; a := a + 1; end;
>
> var obj: T;
> begin
> MyInc2(obj.P);
> end.
> -----
>
> what is the *usual expectation* of the number of calls to GetP and SetP?
> Using temporary variables, there will be one call to each.
Where would you place such temporary variables, in your sample code?
Into an invisible layer between the caller and MyInc2?
> It might be argued that some programmer might expect two calls to each,
> but I am really not sure if such programmer exists ;-)
> Moreover, if we assume the existence of such a hypothetical programmer,
> how could he implement MyInc2 to achieve the behaviour he expects?
> The answer is: he could not. It is impossible with or without the
> proposed extension.
I could follow your argumentation in an example like
for i := 1 to obj.P do ...
where a C programmer would assume any number of calls to obj.GetP, while
a Pascal programmer would be sure that obj.GetP is invoked only once,
and the returned value is stored in a local variable.
> So we must conclude that the possible downside is relatively small.
> It must be weighted against the upside:
>
> Components[ComponentIndex].Options :=
> Components[ComponentIndex].Options + [myOption];
>
> vs
>
> Include(Components[ComponentIndex].Options, myOption);
>
> is, IMO, a very compelling argument.
Right :-)
But again, a C++ programmer would write a macro
#define Inc2(x) {x += 2;}
and use it like
Inc2(obj.P);
where a Pascal programmer would use the compiler magic
Inc(obj.P,2);
because he cannot write macros, and the compiler should[1] do the job
for him.
Unfortunately FPC did a lousy job in the past, using the field address
(returned by @obj.P) to bypass the setter. Strange enough that FPC
realized that a typed constant cannot be written to - it simply could
have detected the same obstacle for a property. [I didn't realize these
flaws until I did some testing just now]
[1] A quick comparison with Delphi 7 revealed:
Delphi notices that a property cannot be passed as a var parameter.
Delphi also denies Inc(obj.P), so that I have to adjust my opinion about
the cleverness of Inc() :-(
[What does not influence my opinion about the *expected* behaviour of
Inc() :-]
DoDi
More information about the Lazarus
mailing list