Sign in Join

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

Mailing lists / fpc-devel / 2011-09

"referenced properties" vs "value properties"

3 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

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

Skybuck Flying

I think the Delphi language has a little problem when it comes to "properties".

I consider C/C++ to be a "value language" or maybe even a "const language" where addresses of classes and fields are constant or hard coded into instructions.

While Delphi is more of a "reference language" or "pointer language" where addresses of classes are stored in data pointers which are used via instructions.

The closest thing to a c++ class is a record in Delphi.

Delphi classes are different from a c++ class, in Delphi a class when instantiated returns a pointer to a class in memory.

This "referenced" design of Delphi is pretty handy, it allows code to refer to the same memory via different pointers which all point to the same memory.

However I do consider "properties" in it's current design to somewhat break with this "referenced design".

Properties in Delphi are more like a "value type", they/the properties also works on "values", the read/write values or records or even entire arrays.

This more or less seems like a design mistake. Perhaps properties should have been always "referenced" as well just like Delphi classes.

(Think of a referenced property as a "var parameter" versus a "copy parameter"
The var parameter would allow changes, while the copy parameter does useless changes.)

The problem with properties currently is that it does not allow partial modification of records or arrays, when a property is of type record or array it's a everything or nothing situation, either the entire record/array is overwritten/returned or nothing at all, this is very inconvenient and also bad for performance.

Delphi programmers have to fall back on pointer types for value types to be used with properties. So Delphi programmers would need to create pointer types again and turn properties into pointer types.

One example of somewhat bad programming is record operator overloading which also requires two values apperently, this means the properties will have to be dereference for example: C = A^ * B^

The operators themselfes do not seem to work with pointer types, so pointers will have to be deferenced, quite a mess.

The solution could be to introduce "referenced properties". These properties under-water always work with pointers to fields, records, arrays and so forth.

This frees the programmer from having to deal with pointers and pointer types and pointer dereferencing and reduces coding mistakes and also makes coding more efficient/faster/less code needed.

A possible syntax could be as follows:

type
    TSomeClass = class
    private
    protected
        mMyArray : TSomeBigArrayType;
    public
        referenced property SomeBigArray : TSomeBigArrayType read mMyArray;
    end;

(a write mMyArray would be superflous but could also be allowed for easy changing between referenced and non-referenced/value properties, but simply ignored by compiler).

The above syntax would treat access to SomeBigArray via a pointer under water.

So writing:

SomeClass.SomeBigArray[100] := 500;

would automatically retrieve a pointer to the array and apply the index operator on the dereferenced pointer, instead of reading the entire array onto a stack copy and then overwrriten entire 100 and then dumping the entire array into obvlious with the code having no effect as it would in Delphi, where this to be a static array ;)

The code might happen to work for dynamic arrays, since those are too pointers underneath, however for static arrays or for example records, the useless behaviour would be there.

Other problems with properties as already indicated:

property MyRecord : TRecord read mMyRecord
MyRecord.SomeField := 100 <- currently leads to useless code, the record
would be copied onto stack, modified and dumped.

Again the programmer has to write:

property MyRecord : PRecord read GetMyRecordPointer;
MyRecord.SomeField := 100; // now it would work via a pointer, because the
programmer programmed it like that.

Delphi's referenced properties would do away with this extra code and do it automatically as follows:

referenced property MyRecord : TRecord read mMyRecord;
MyRecord.SomeField := 100;

An alternative syntax could also be:

property MyRecord : TRecord access mMyRecord;

or as I already wrote a long time ago:

property MyRecord : TRecord address mMyRecord;

or perhaps:

property MyRecord : TRecord reference mMyRecord;

Anything to solve the current situation would be nice, how would you solve the problem and automate it ?

For now it seems best to avoid "records" as the plague and always use "classes".

There is one catch22/drawback, classes don't have operator overloading.

However somebody wrote "record operators" are slow so perhaps it's for the better.

Bye,
Skybuck.

Reply by email

Martin
to Skybuck Flying
Skybuck Flying wrote 6 lines
The problem with properties currently is that it does not allow partial modification of records or arrays, when a property is of type record or array it's a everything or nothing situation, either the entire record/array is overwritten/returned or nothing at all, this is very inconvenient and also bad for performance.

This is not the prolem with properties. This is what "property" means in pascal. This is the reason why there is a you don't want that, do not use a property, just use a field (member/variable) instead.

you can always do
   TFoo =Class
   public
     Bar: TSomeRecord; // field/variable
   end;

And all will work.

The main reason to use a property

   property Bar: TSomeRecord read Fbar write FBar

is to declare that the implementer reserves the right, to later put getter/setter function/procedures in place

It tells the compiler, that while the developer did not yet write any such code, the compiler should/must protect "Bar" in a way that any code referring to it, will work, if getter/setters are written.

But with a getter, Bar is a function result => so you can not do
   GetBar().xyz := 1
At least not meaningful: because you do not have the original FBar, you
only have a temporary copy returned by GetBar.
Even if pascal would have functions that return lvalues, GetBar could
have created a result on the fly. There may not be a FBar  GetBar: TSomeRecord;
   begin
     Result.xyz := random(5);
   end;
With this function, what you suppose that "Bar.xyz := 1;" should do?
Since Bar is GetBar, which retturns a record created on the fly, that
will be dropped straight away

The only way ossible would be for the compiler to translate it into

   tmp := Bar;  tmp.xyz := 1; Bar:=tmp;

which would be the same as

   tmp := GetBar();  tmp.xyz := 1; SetBar(tmp);

And SetBar could have plenty of side effects, that do far more than just updating xyz.The original code never said to update the entire "Bar" => so it must not be translated to do so.

So again: using the keyword property means =>assume there is no variable at all; assume it may be a function, getter/setter ....

If you do not want that, do not use it.

There is no rule, that you must use properties. Making a field public accessible is absolutely ok.
Most peopl edo not do it => because, if uou do not have a specific reason to do it, then using property means that at absolutely no cost, you can reserve the possibility of future extension should you need to. Hence, unless you have a good reason not to use property, you should use it. But if your design does not allow for it, do not use it.

Reply by email

Hans-Peter Diettrich
to Skybuck Flying: I think the Delphi language has a little problem when it comes to "properties". I…
Show quoted text 10 lines
I think the Delphi language has a little problem when it comes to "properties". I consider C/C++ to be a "value language" or maybe even a "const language" where addresses of classes and fields are constant or hard coded into instructions. While Delphi is more of a "reference language" or "pointer language" where addresses of classes are stored in data pointers which are used via instructions.

A closer look will reveal that references had to be introduced into the C++ language, in order to make operators work with certain data types (arrays...).

The closest thing to a c++ class is a record in Delphi.

Closest comes the Object type, but Borland/CodeGear decided to drop that useful type, and moved part of its features into records (methods...). FPC still supports Object very well.

The problem with properties currently is that it does not allow partial modification of records or arrays

That's due to the (possibly) virtual getters/setters, which make properties a really useful language feature. If you want references, then use data fields (var) instead of properties.

The operators themselfes do not seem to work with pointer types, so pointers will have to be deferenced, quite a mess.

See C++.

DoDi

Reply by email