Sign in Join

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

Mailing lists / fpc-pascal / 2019-06

Class field property access

9 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

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

Ryan Joseph

I found a restriction in properties which is a little disappointing. I get there’s probably some objective of safety but Pascal is a direct memory access language so I don’t understand why properties have this unique restriction when I could do the same thing using functions (pointers can’t be dereferenced in properties either). Shouldn’t I as the programmer get to decide whether the property is safe or not based upon when I call it?

type
  TB = class
    x: integer;
  end;
type
  TA = class
    private
      b: TB;
    public
      property x: integer read b.x;	// ERROR: Must be a record/object type
  end;

Regards,
Ryan Joseph

Reply by email

Tomas Hajny
to Ryan Joseph
Ryan Joseph wrote 21 lines
I found a restriction in properties which is a little disappointing. I get there’s probably some objective of safety but Pascal is a direct memory access language so I don’t understand why properties have this unique restriction when I could do the same thing using functions (pointers can’t be dereferenced in properties either). Shouldn’t I as the programmer get to decide whether the property is safe or not based upon when I call it? type TB = class x: integer; end; type TA = class private b: TB; public property x: integer read b.x; // ERROR: Must be a record/object type end;

Which mode / which FPC version? It compiles without complaints for me with FPC 3.0.4 and either -Mobjfpc or -Mdelphi (after adding 'begin end.' to the end to make it a valid / compilable "program".

Tomas

Reply by email

Sven Barth
to Ryan Joseph: I found a restriction in properties which is a little disappointing. I get there’s…

Ryan Joseph schrieb am Mo., 3. Juni 2019,
16:36:

Show quoted text 21 lines
I found a restriction in properties which is a little disappointing. I get there’s probably some objective of safety but Pascal is a direct memory access language so I don’t understand why properties have this unique restriction when I could do the same thing using functions (pointers can’t be dereferenced in properties either). Shouldn’t I as the programmer get to decide whether the property is safe or not based upon when I call it? type TB = class x: integer; end; type TA = class private b: TB; public property x: integer read b.x; // ERROR: Must be a record/object type end;

The b field could be Nil and the class might not provide any functionality to check for that. In addition to that it's an additional indirection while records/objects merely require an offset.

Regards,
Sven

Reply by email

Ryan Joseph
to Sven Barth
On Jun 3, 2019, at 11:13 AM, Sven Barth via fpc-pascal wrote: The b field could be Nil and the class might not provide any functionality to check for that. In addition to that it's an additional indirection while records/objects merely require an offset.

{ I’ve resubscribed to the list with a new email since the mail server wasn’t liking my old one. Resending this message since it was rejected before. }

But my point is Pascal allows this kind of behavior so why are properties different? Who cares if there is an additional level of indirection? This appears to be a regression since 3.0.4 also. Did you specifically disable this in 3.3.1? Sorry I’m not understanding this one.

Regards,
Ryan Joseph

Reply by email

Michael Van Canneyt
to Ryan Joseph
Ryan Joseph wrote 11 lines
> On Jun 3, 2019, at 11:13 AM, Sven Barth via fpc-pascal wrote: > > The b field could be Nil and the class might not provide any functionality to check for that. In addition to that it's an additional indirection while records/objects merely require an offset. > { I’ve resubscribed to the list with a new email since the mail server wasn’t liking my old one. Resending this message since it was rejected before. } But my point is Pascal allows this kind of behavior so why are properties different?

What kind of behaviour are you referring to.

Who cares if there is an additional level of indirection?

Because the indirection may not be there.
The compiler cannot guarantee that, thus leading to access violations.

You can use a getter function to get the desired property. In the getter you can decide what to do: create the b instance (sometimes a valid choice) or raise an error.

But the compiler cannot take this decision for you, so b.x is not allowed.

This appears to be a regression since 3.0.4 also. Did you specifically disable this in 3.3.1? Sorry I’m not understanding this one.

If it was allowed in previous versions, this was by accident allowed during parsing and most likely simply didn't work in reality.

Michael.

Reply by email

Sven Barth
to Michael Van Canneyt

Michael Van Canneyt schrieb am Fr., 7. Juni 2019, 08:52:

Show quoted text 6 lines
> This appears to be a regression since 3.0.4 also. Did you specifically > disable this in 3.3.1? Sorry I’m not understanding this one. If it was allowed in previous versions, this was by accident allowed during parsing and most likely simply didn't work in reality.

Correct:
http://wiki.freepascal.org/User_Changes_Trunk#Property_field_access_lists_no_longer_allows_classes

Regards,
Sven

Reply by email

Ryan Joseph
to Michael Van Canneyt: What kind of behaviour are you referring to. Because the indirection may not be there.…
On Jun 7, 2019, at 2:51 AM, Michael Van Canneyt wrote: What kind of behaviour are you referring to.

Something wrong with my mail server causing your server to block me (Jonas said my server didn’t handle greylisting correctly). Easier to just re-sub using gmail for now.

Show quoted text 9 lines
> Who cares if there is an additional level of indirection? Because the indirection may not be there. The compiler cannot guarantee that, thus leading to access violations. You can use a getter function to get the desired property. In the getter you can decide what to do: create the b instance (sometimes a valid choice) or raise an error. But the compiler cannot take this decision for you, so b.x is not allowed.

I really have to question the wisdom of this. The code below works in 3.0.4 and is completely safe. I understand there was delphi compatibility and problems with published properties however but that could have been worked around easily. Maybe it’s a not big deal in the grand scheme of things but writing boiler plate like getters/setters is not fun.

type
TB = class
  x: integer;
end;
type
 TA = class
  private
    b: TB;
  public
    property x: integer read b.x write b.x;
    procedure AfterConstruction; override;
end;
procedure TA.AfterConstruction;
begin
 b := TB.Create;
end;
var
 a: TA;
begin
 a := TA.Create;
 a.x := 100;
 writeln(a.x);
end.

Regards,
Ryan Joseph

Reply by email

Sven Barth
to Ryan Joseph

Ryan Joseph schrieb am Fr., 7. Juni 2019, 14:00:

Show quoted text 11 lines
> On Jun 7, 2019, at 2:51 AM, Michael Van Canneyt wrote: > > What kind of behaviour are you referring to. Something wrong with my mail server causing your server to block me (Jonas said my server didn’t handle greylisting correctly). Easier to just re-sub using gmail for now.

Michael meant this:

But my point is Pascal allows this kind of behavior so why are properties different?
Show quoted text 48 lines
> >> Who cares if there is an additional level of indirection? > > Because the indirection may not be there. The compiler cannot guarantee that, thus leading to access violations. > > You can use a getter function to get the desired property. In the getter you > can decide what to do: create the b instance (sometimes a valid choice) or raise an error. > > But the compiler cannot take this decision for you, so b.x is not allowed. I really have to question the wisdom of this. The code below works in 3.0.4 and is completely safe. I understand there was delphi compatibility and problems with published properties however but that could have been worked around easily. Maybe it’s a not big deal in the grand scheme of things but writing boiler plate like getters/setters is not fun. type TB = class x: integer; end; type TA = class private b: TB; public property x: integer read b.x write b.x; procedure AfterConstruction; override; end; procedure TA.AfterConstruction; begin b := TB.Create; end; var a: TA; begin a := TA.Create; a.x := 100; writeln(a.x); end.

Only because this example appears safe does not mean that the whole concept is safe.
A class might initialize b only later on and with a direct property you'll only get an access violation. So you'll need a getter anyway to provide a better exception type. Or to dynamically create the object instance.

I see no reason to revert this change.

Regards,
Sven

Reply by email

Ryan Joseph
to Sven Barth
Show quoted text 6 lines
On Jun 7, 2019, at 8:08 AM, Sven Barth via fpc-pascal wrote: Only because this example appears safe does not mean that the whole concept is safe. A class might initialize b only later on and with a direct property you'll only get an access violation. So you'll need a getter anyway to provide a better exception type. Or to dynamically create the object instance. I see no reason to revert this change.

Well, the consequence is that programmers that now know how to be safe are going to have to do more work by writing getters/setters. Pascal allows potentially unsafe memory access in all other situations so I don’t see why properties are any different. We’re targeting the lowest common denominator instead of allowing careful programers to do their best.

Regards,
Ryan Joseph

Reply by email