Sign in Join

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

Mailing lists / fpc-pascal / 2013-10

private type and type compatibility

39 messages · 8 people · –

Reply by email Subscribe to this list Your subscription

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

Xiangrong Fang

Hi All,

I have the following class:

type
  generic TVector<T> = class
  private type
    TDataType = array of T;
  private
    FData: TDataType;
    ... ...
  public
    ... ...
    function Slice(APos: Integer = -1; ACount: Integer = -1): TDataType;
  end;

The Slice() method return a portion of the data as a dynamic array.

My question is, as I define TDataType as PRIVATE type, why it is still usable outside of the class? In the main program I did:

type
  TIntVector = specialize TVector<Integer>;
var
  iv: TIntVector;
  ia: array of Integer;
begin
  iv := TIntVector.Create;
  ... ...
  ia := iv.Slice;
end.

This will assign a TDataType (is it TVector$TDataType or TIntVector$TDataType? I don't know) to an "array of Integer". Why this assignment works?

i.e. how does the type system work?!

Best Regards,
Xiangrong

Reply by email

Sven Barth
to Xiangrong Fang
Xiangrong Fang wrote 37 lines
Hi All, I have the following class: type generic TVector<T> = class private type TDataType = array of T; private FData: TDataType; ... ... public ... ... function Slice(APos: Integer = -1; ACount: Integer = -1): TDataType; end; The Slice() method return a portion of the data as a dynamic array. My question is, as I define TDataType as PRIVATE type, why it is still usable outside of the class? In the main program I did: type TIntVector = specialize TVector<Integer>; var iv: TIntVector; ia: array of Integer; begin iv := TIntVector.Create; ... ... ia := iv.Slice; end. This will assign a TDataType (is it TVector$TDataType or TIntVector$TDataType? I don't know) to an "array of Integer". Why this assignment works? i.e. how does the type system work?!

It's a bit annoying that the usage private/protected types in public/published functions is allowed... (this is however Delphi compatible) Maybe this should be adjusted for non-Delphi modes for language consistency... (maybe at least as a warning which could be elevated to an error if someone wants)

Regards,
Sven

Reply by email

Michael Van Canneyt
to Sven Barth
Sven Barth wrote 41 lines
Am 30.10.2013 08:47, schrieb Xiangrong Fang: Hi All, I have the following class: type   generic TVector<T> = class   private type     TDataType = array of T;   private     FData: TDataType;     ... ...   public     ... ...     function Slice(APos: Integer = -1; ACount: Integer = -1): TDataType;   end; The Slice() method return a portion of the data as a dynamic array. My question is, as I define TDataType as PRIVATE type, why it is still usable outside of the class?  In the main program I did: type   TIntVector = specialize TVector<Integer>; var   iv: TIntVector;   ia: array of Integer; begin   iv := TIntVector.Create;   ... ...   ia := iv.Slice; end. This will assign a TDataType (is it TVector$TDataType or TIntVector$TDataType? I don't know) to an "array of Integer". Why this assignment works?  i.e. how does the type system work?! It's a bit annoying that the usage private/protected types in public/published functions is allowed... (this is however Delphi compatible) Maybe this should be adjusted for non-Delphi modes for language consistency... (maybe at least as a warning which could be elevated to an error if someone wants)

I think it is an error.
You declare something as private, and then you use it in a public function ? If that is not a visibility clash, I don't know what is :)

Michael.

Reply by email

Sven Barth
to Michael Van Canneyt
Michael Van Canneyt wrote 54 lines
On Wed, 30 Oct 2013, Sven Barth wrote: > Am 30.10.2013 08:47, schrieb Xiangrong Fang: > Hi All, > > I have the following class: > > type > generic TVector<T> = class > private type > TDataType = array of T; > private > FData: TDataType; > ... ... > public > ... ... > function Slice(APos: Integer = -1; ACount: Integer = -1): > TDataType; > end; > > The Slice() method return a portion of the data as a dynamic array. > > My question is, as I define TDataType as PRIVATE type, why it is > still usable outside of the class? In the main program > I did: > > type > TIntVector = specialize TVector<Integer>; > var > iv: TIntVector; > ia: array of Integer; > begin > iv := TIntVector.Create; > ... ... > ia := iv.Slice; > end. > > This will assign a TDataType (is it TVector$TDataType or > TIntVector$TDataType? I don't know) to an "array of Integer". > Why this assignment works? > > i.e. how does the type system work?! > > It's a bit annoying that the usage private/protected types in > public/published functions is allowed... (this is however Delphi > compatible) Maybe this should be adjusted for non-Delphi modes for > language consistency... (maybe at least as a warning which > could be elevated to an error if someone wants) I think it is an error. You declare something as private, and then you use it in a public function ? If that is not a visibility clash, I don't know what is :)

I agree, but the question is should we declare this as a bug in the language and thus fix it which might lead to adjustments of legacy (2.6.x) code or use a warning. I personally would do the former (and better sooner than later). We need to keep the current behavior in mode Delphi however... (Note: Delphi additionally allows to access protected types from external units; could be related to the point that helper types allow access to protected types and fields as well...)

Regards,
Sven

Reply by email

Xiangrong Fang
to Sven Barth

2013/10/30 Sven Barth

Show quoted text 12 lines
I think it is an error. You declare something as private, and then you use > it in a public function ? If that is not a visibility clash, I don't know > what is :) > I agree, but the question is should we declare this as a bug in the language and thus fix it which might lead to adjustments of legacy (2.6.x) code or use a warning. I personally would do the former (and better sooner than later). We need to keep the current behavior in mode Delphi however... (Note: Delphi additionally allows to access protected types from external units; could be related to the point that helper types allow access to protected types and fields as well...)

​I also agree that it is a bug. That's why I am confused.​

Reply by email

Michael Van Canneyt
to Sven Barth: I agree, but the question is should we declare this as a bug in the language and thus fix…
Sven Barth wrote 58 lines
Am 30.10.2013 10:36, schrieb Michael Van Canneyt: > > > On Wed, 30 Oct 2013, Sven Barth wrote: > >> Am 30.10.2013 08:47, schrieb Xiangrong Fang: >> Hi All, >> >> I have the following class: >> >> type >> generic TVector<T> = class >> private type >> TDataType = array of T; >> private >> FData: TDataType; >> ... ... >> public >> ... ... >> function Slice(APos: Integer = -1; ACount: Integer = -1): >> TDataType; >> end; >> >> The Slice() method return a portion of the data as a dynamic array. >> >> My question is, as I define TDataType as PRIVATE type, why it is still >> usable outside of the class? In the main program >> I did: >> >> type >> TIntVector = specialize TVector<Integer>; >> var >> iv: TIntVector; >> ia: array of Integer; >> begin >> iv := TIntVector.Create; >> ... ... >> ia := iv.Slice; >> end. >> >> This will assign a TDataType (is it TVector$TDataType or >> TIntVector$TDataType? I don't know) to an "array of Integer". >> Why this assignment works? >> >> i.e. how does the type system work?! >> >> It's a bit annoying that the usage private/protected types in >> public/published functions is allowed... (this is however Delphi >> compatible) Maybe this should be adjusted for non-Delphi modes for >> language consistency... (maybe at least as a warning which >> could be elevated to an error if someone wants) > > I think it is an error. You declare something as private, and then you use > it in a public function ? If that is not a visibility clash, I don't know > what is :) I agree, but the question is should we declare this as a bug in the language and thus fix it which might lead to adjustments of legacy (2.6.x) code or use a warning. I personally would do the former (and better sooner than later).

Me too. It is a bug, and should be treated as such.

Micihael.

Reply by email

Jonas Maebe
to Michael Van Canneyt: I think it is an error. You declare something as private, and then you use it in a public…
Michael Van Canneyt wrote
I think it is an error. You declare something as private, and then you use it in a public function ? If that is not a visibility clash, I don't know what is :)

The ability to use types in public functions that are not necessarily visible to users of that function is quite common in Pascal. Otherwise, for consistency you would also have to give a compile time error when compiling this:

unit u1;
interface
type
   tdynarray = array of integer;
implementation
end.
*********
unit u2;
interface
uses
   u1;
function f: tdynarray;
implementation
function f: tdynarray;
begin
end;
end.
**********
program test;
uses
   u2;
var
   a: array of integer;
begin
   a:=f;
end.
***

The tdynarray type is not visible in the program because u1 is not in its uses clause (it's not in scope whatsoever), and nevertheless there is no problem to use it. It's of course not exactly the same (tdynarray isn't declared as private to u1), but at the scope visibility level it is the same situation as far as I am concerned.

Jonas

Reply by email

Frederic Da Vitoria
to Jonas Maebe

2013/10/30 Jonas Maebe

Show quoted text 60 lines
On 30 Oct 2013, at 10:36, Michael Van Canneyt wrote: I think it is an error. You declare something as private, and then you > use it in a public function ? If that is not a visibility clash, I don't > know what is :) > The ability to use types in public functions that are not necessarily visible to users of that function is quite common in Pascal. Otherwise, for consistency you would also have to give a compile time error when compiling this: unit u1; interface type tdynarray = array of integer; implementation end. ********* unit u2; interface uses u1; function f: tdynarray; implementation function f: tdynarray; begin end; end. ********** program test; uses u2; var a: array of integer; begin a:=f; end. *** The tdynarray type is not visible in the program because u1 is not in its uses clause (it's not in scope whatsoever), and nevertheless there is no problem to use it. It's of course not exactly the same (tdynarray isn't declared as private to u1), but at the scope visibility level it is the same situation as far as I am concerned.

Precisely, shouldn't this trigger an error too? The code should not be able to reference anything for which the declaration isn't visible, isn't it?

Frederic Da Vitoria (davitof) Membre de l'April - « promouvoir et défendre le logiciel libre » - http://www.april.org

Reply by email

Sven Barth
to Jonas Maebe: The ability to use types in public functions that are not necessarily visible to users of…
Jonas Maebe wrote 59 lines
On 30 Oct 2013, at 10:36, Michael Van Canneyt wrote: > I think it is an error. You declare something as private, and then > you use it in a public function ? If that is not a visibility clash, > I don't know what is :) The ability to use types in public functions that are not necessarily visible to users of that function is quite common in Pascal. Otherwise, for consistency you would also have to give a compile time error when compiling this: unit u1; interface type tdynarray = array of integer; implementation end. ********* unit u2; interface uses u1; function f: tdynarray; implementation function f: tdynarray; begin end; end. ********** program test; uses u2; var a: array of integer; begin a:=f; end. *** The tdynarray type is not visible in the program because u1 is not in its uses clause (it's not in scope whatsoever), and nevertheless there is no problem to use it. It's of course not exactly the same (tdynarray isn't declared as private to u1), but at the scope visibility level it is the same situation as far as I am concerned.

Hmm... but here the compiler can not know whether the unit using u2 has unit u1 in scope or not. In case of private and protected types the compiler can know however that code declared externally can never have access to it (though of course there might be type compatibilities like your dynamic array example, but most private/protected types should be records or classes).

Regards,
Sven

Reply by email

Sven Barth
to Frederic Da Vitoria: 2013/10/30 Jonas Maebe Precisely, shouldn't this trigger an error too? The code should…
Frederic Da Vitoria wrote 68 lines
2013/10/30 Jonas Maebe < > On 30 Oct 2013, at 10:36, Michael Van Canneyt wrote: I think it is an error. You declare something as private, and then you use it in a public function ? If that is not a visibility clash, I don't know what is :) The ability to use types in public functions that are not necessarily visible to users of that function is quite common in Pascal. Otherwise, for consistency you would also have to give a compile time error when compiling this: unit u1; interface type tdynarray = array of integer; implementation end. ********* unit u2; interface uses u1; function f: tdynarray; implementation function f: tdynarray; begin end; end. ********** program test; uses u2; var a: array of integer; begin a:=f; end. *** The tdynarray type is not visible in the program because u1 is not in its uses clause (it's not in scope whatsoever), and nevertheless there is no problem to use it. It's of course not exactly the same (tdynarray isn't declared as private to u1), but at the scope visibility level it is the same situation as far as I am concerned. Precisely, shouldn't this trigger an error too? The code should not be able to reference anything for which the declaration isn't visible, isn't it?

But the compiler can not know whether the user of unit u2 has unit u1 in scope or not.

Regards,
Sven

Reply by email

Michael Van Canneyt
to Sven Barth: Hmm... but here the compiler can not know whether the unit using u2 has unit u1 in scope…
Sven Barth wrote 8 lines
Am 30.10.2013 11:59, schrieb Jonas Maebe: > > problem to use it. It's of course not exactly the same (tdynarray isn't > declared as private to u1), but at the scope visibility level it is the > same situation as far as I am concerned. Hmm... but here the compiler can not know whether the unit using u2 has unit u1 in scope or not. In case of private and protected types the compiler can know however that code declared externally can never have access to it

My thoughts exactly.

In the case of units, the user CAN make it visible (as in : directly accessible) by adding the unit to the uses clause. He can never do this for the private type.

Michael.

Reply by email

Jonas Maebe
to Sven Barth: Hmm... but here the compiler can not know whether the unit using u2 has unit u1 in scope…
Sven Barth wrote
Am 30.10.2013 11:59, schrieb Jonas Maebe: > > The tdynarray type is not visible in the program because u1 is not in its uses clause (it's not in scope whatsoever), and nevertheless there is no problem to use it. It's of course not exactly the same (tdynarray isn't declared as private to u1), but at the scope visibility level it is the same situation as far as I am concerned. Hmm... but here the compiler can not know whether the unit using u2 has unit u1 in scope or not. In case of private and protected types the compiler can know however that code declared externally can never have access to it

It can, as demonstrated by the example that started this thread. The type identifier may not be visible, but entities that have this type can be. Just like in the unit example.

(though of course there might be type compatibilities like your dynamic array example, but most private/protected types should be records or classes).

I'm not sure why most private types "should" be records/classes, especially with generic classes.

Jonas

Reply by email

Michael Van Canneyt
to Jonas Maebe
Jonas Maebe wrote 9 lines
On 30 Oct 2013, at 12:09, Sven Barth wrote: > Am 30.10.2013 11:59, schrieb Jonas Maebe: >> >> The tdynarray type is not visible in the program because u1 is not in its uses clause (it's not in scope whatsoever), and nevertheless there is no problem to use it. It's of course not exactly the same (tdynarray isn't declared as private to u1), but at the scope visibility level it is the same situation as far as I am concerned. > Hmm... but here the compiler can not know whether the unit using u2 has unit u1 in scope or not. In case of private and protected types the compiler can know however that code declared externally can never have access to it It can, as demonstrated by the example that started this thread. The type identifier may not be visible, but entities that have this type can be. Just like in the unit example.

You must admit that in the case of a function result type, that is a bit awkward, since you will never be able to declare a properly typed variable to hold the function result. In the case of a record or class type, that is particularly awkward since you will be forced to use a "with" to access the various fields.

Type
   TMyClass = Class
   private
    type myrec = record
     a,b : SomeOtherType;
     end;
   public
     function MyFunc : Myrec;
   end;

You cannot do

Var
   c : TMyClass;
   r : myrec; // will fail.
begin
   r:=c.myfunc;
   Writeln(r.a,' ',r.b);
end;

you can only do

Var
   c : TMyClass;
begin
   with c.myfunc do
     Writeln(r.a,' ',r.b);
end;

Michael.

Reply by email

Jonas Maebe
to Michael Van Canneyt
Michael Van Canneyt wrote 11 lines
On Wed, 30 Oct 2013, Jonas Maebe wrote: > It can, as demonstrated by the example that started this thread. > The type identifier may not be visible, but entities that have this > type can be. Just like in the unit example. You must admit that in the case of a function result type, that is a bit awkward, since you will never be able to declare a properly typed variable to hold the function result. In the case of a record or class type, that is particularly awkward since you will be forced to use a "with" to access the various fields.

Absolutely, but it's always been valid in TP/Delphi/FPC-style Pascal and introducing a special rule would make the language less orthogonal.

Jonas

Reply by email

Michael Van Canneyt
to Jonas Maebe
Jonas Maebe wrote 17 lines
On 30 Oct 2013, at 12:50, Michael Van Canneyt wrote: > On Wed, 30 Oct 2013, Jonas Maebe wrote: > >> It can, as demonstrated by the example that started this thread. The type >> identifier may not be visible, but entities that have this type can be. >> Just like in the unit example. > > You must admit that in the case of a function result type, that is a bit > awkward, since you will never be able to declare a properly typed variable > to hold the function result. In the case of a record or class type, that is > particularly awkward since you will be forced to use a "with" to access the > various fields. Absolutely, but it's always been valid in TP/Delphi/FPC-style Pascal and introducing a special rule would make the language less orthogonal.

I still think it is a different use case:

Like I said: in the case of an identifier from a different unit, the user just has to add it to her uses clause. Here this is simply impossible.

It is probably the reason why in the original TP manuals it stated that "adding a unit B to the interface section's uses clause of unit A makes identifiers in the interface section of unit B available to all code using unit A."

Michael.

Reply by email

Jonas Maebe
to Michael Van Canneyt
Michael Van Canneyt wrote 19 lines
On Wed, 30 Oct 2013, Jonas Maebe wrote: > On 30 Oct 2013, at 12:50, Michael Van Canneyt wrote: > >> You must admit that in the case of a function result type, that is >> a bit awkward, since you will never be able to declare a properly >> typed variable to hold the function result. In the case of a >> record or class type, that is particularly awkward since you will >> be forced to use a "with" to access the various fields. > > Absolutely, but it's always been valid in TP/Delphi/FPC-style > Pascal and introducing a special rule would make the language less > orthogonal. I still think it is a different use case: Like I said: in the case of an identifier from a different unit, the user just has to add it to her uses clause. Here this is simply impossible.

My point is that even without adding that other unit, you can still "consume" values that have this type even though the type declarations are not in scope. You can indeed not add them in the scope here, but they are still usable.

Jonas

Reply by email

Michael Van Canneyt
to Jonas Maebe
Jonas Maebe wrote 25 lines
On 30 Oct 2013, at 13:05, Michael Van Canneyt wrote: > On Wed, 30 Oct 2013, Jonas Maebe wrote: > >> On 30 Oct 2013, at 12:50, Michael Van Canneyt wrote: >> >>> You must admit that in the case of a function result type, that is a bit >>> awkward, since you will never be able to declare a properly typed >>> variable to hold the function result. In the case of a record or class >>> type, that is particularly awkward since you will be forced to use a >>> "with" to access the various fields. >> >> Absolutely, but it's always been valid in TP/Delphi/FPC-style Pascal and >> introducing a special rule would make the language less orthogonal. > > I still think it is a different use case: > > Like I said: in the case of an identifier from a different unit, the user > just has to add it to her uses clause. Here this is simply impossible. My point is that even without adding that other unit, you can still "consume" values that have this type even though the type declarations are not in scope. You can indeed not add them in the scope here, but they are still usable.

Yes, I understood it like that.
I do think it is a design fault (see the remark about the TP manuals), but that is another issue.

Michael.

Reply by email

Xiangrong Fang
to Jonas Maebe: The ability to use types in public functions that are not necessarily visible to users of…

2013/10/30 Jonas Maebe

Show quoted text 5 lines
The tdynarray type is not visible in the program because u1 is not in its uses clause (it's not in scope whatsoever), and nevertheless there is no problem to use it. It's of course not exactly the same (tdynarray isn't declared as private to u1), but at the scope visibility level it is the same situation as far as I am concerned.

​I don't think they are the same. tdynarray​
is not usable in main program because you did not uses u1, NOT because the type is defined as PRIVATE!

​As a matter of fact, if you define tdynarray as private (not in interface section), there is no way you can use it as a return type of an exported (public) function. ​This is a very consistent scoping rule!

In my example, if the code is like this:

generic TVector<T> = class
private type
  TDataType = array of T;
private
  function proc: TDataType;
end;

Then I think it is ok, because this PRIVATE type is used by PRIVATE function.

What do you think?

Sincerely,
Xiangrong

Reply by email

Jonas Maebe
to Xiangrong Fang
Xiangrong Fang wrote 16 lines
2013/10/30 Jonas Maebe > The tdynarray type is not visible in the program because u1 is not > in its > uses clause (it's not in scope whatsoever), and nevertheless there > is no > problem to use it. It's of course not exactly the same (tdynarray > isn't > declared as private to u1), but at the scope visibility level it is > the > same situation as far as I am concerned. ​I don't think they are the same. tdynarray​ is not usable in main program because you did not uses u1, NOT because the type is defined as PRIVATE!

"Private" is just another way to define a scope, just like a unit interface and implementation define a scope. Neither the "private" section nor the interface of unit "u1" is in scope when the "hidden" type is used.

Jonas

Reply by email

Martin
to Xiangrong Fang: 2013/10/30 Jonas Maebe ​I don't think they are the same. tdynarray​ is not usable in…
Xiangrong Fang wrote 32 lines
2013/10/30 Jonas Maebe < > The tdynarray type is not visible in the program because u1 is not in its uses clause (it's not in scope whatsoever), and nevertheless there is no problem to use it. It's of course not exactly the same (tdynarray isn't declared as private to u1), but at the scope visibility level it is the same situation as far as I am concerned. I don't think they are the same. tdynarray is not usable in main program because you did not uses u1, NOT because the type is defined as PRIVATE! As a matter of fact, if you define tdynarray as private (not in interface section), there is no way you can use it as a return type of an exported (public) function. This is a very consistent scoping rule! In my example, if the code is like this: generic TVector<T> = class private type TDataType = array of T; private function proc: TDataType; end; Then I think it is ok, because this PRIVATE type is used by PRIVATE function. What do you think?

I think there is no problem with:

var
   a: array of Integer
begin
   A:= obj.proc;

You are NOT using the type. You are using the value.

Reply by email

Xiangrong Fang
to Sven Barth: It's a bit annoying that the usage private/protected types in public/published functions…

2013/10/30 Sven Barth

Show quoted text 6 lines
It's a bit annoying that the usage private/protected types in public/published functions is allowed... (this is however Delphi compatible) Maybe this should be adjusted for non-Delphi modes for language consistency... (maybe at least as a warning which could be elevated to an error if someone wants)

​Alternatively, consider do NOT allow access modifiers for NESTED types, instead, the visibility of nested types follow the class they are embeded in. Anyway, what is the purpose of HIDE a nested type?

Regards,
Xiangrong​

Reply by email

Xiangrong Fang
to Martin: I think there is no problem with: var a: array of Integer begin A:= obj.proc; You are NOT…

2013/10/30 Martin

Show quoted text 10 lines
I think there is no problem with: var a: array of Integer begin A:= obj.proc; You are NOT using the type. You are using the value.

pascal is strong-typed. You are actually using type along with its value. e.g.

var
  a: array of Double;
begin
  a := obj.proc;​​

This will emit a COMPILE time error because compiler know these 2 types are not compatible.

Reply by email

Jonas Maebe
to Xiangrong Fang
Xiangrong Fang wrote 12 lines
pascal is strong-typed. You are actually using type along with its value. e.g. var a: array of Double; begin a := obj.proc;​​ This will emit a COMPILE time error because compiler know these 2 types are not compatible.

No, it does not cause an error. Pascal indeed does not use structural compatibility for record/object/class types (two record/object/class types with exactly the same fields are not assignment-compatible), but for other types such as integer/float types (because of implicit conversion) and arrays you have more "cross-type" compatibility.

Jonas

Reply by email

Sven Barth
to Jonas Maebe: "Private" is just another way to define a scope, just like a unit interface and…
Jonas Maebe wrote 22 lines
On 30 Oct 2013, at 14:30, Xiangrong Fang wrote: > 2013/10/30 Jonas Maebe > >> The tdynarray type is not visible in the program because u1 is not >> in its >> uses clause (it's not in scope whatsoever), and nevertheless there >> is no >> problem to use it. It's of course not exactly the same (tdynarray isn't >> declared as private to u1), but at the scope visibility level it is the >> same situation as far as I am concerned. > > ​I don't think they are the same. tdynarray​ > is not usable in main program because you did not uses u1, NOT > because the > type is defined as PRIVATE! "Private" is just another way to define a scope, just like a unit interface and implementation define a scope. Neither the "private" section nor the interface of unit "u1" is in scope when the "hidden" type is used.

Using an interface uses as the analog for private types is flawed in my opinion. The analog code would more like this:

=== code begin ===

unit u2;
interface
function f: tdynarray;
implementation
type
   tdynarray = array of integer;
function f: tdynarray;
begin
end;
end.

=== code end ===

Which of course does not compile. The same should be the case for private type declarations used in public ones...

Regards,
Sven

Reply by email

Martin
to Xiangrong Fang: 2013/10/30 Martin pascal is strong-typed. You are actually using type along with its…
Xiangrong Fang wrote 24 lines
2013/10/30 Martin < > I think there is no problem with: var a: array of Integer begin A:= obj.proc; You are NOT using the type. You are using the value. pascal is strong-typed. You are actually using type along with its value. e.g. var a: array of Double; begin a := obj.proc; This will emit a COMPILE time error because compiler know these 2 types are not compatible.

Yes. But what I mean is, your code does not refer to the type directly.

Since the type is part of value, and the value is public, all of the type that is accessed through the value is available. Same as you can access a private field through a public property.

However the type itself (as referenced by the identifier in the type declaration), that is the type without a value, is not used by your code. You do not declare a new variable of that type.

Reply by email

Jonas Maebe
to Sven Barth: Using an interface uses as the analog for private types is flawed in my opinion. The…
Sven Barth wrote 32 lines
Am 30.10.2013 14:37, schrieb Jonas Maebe: > > "Private" is just another way to define a scope, just like a unit > interface and implementation define a scope. Neither the "private" > section nor the interface of unit "u1" is in scope when the > "hidden" type is used. Using an interface uses as the analog for private types is flawed in my opinion. The analog code would more like this: === code begin === unit u2; interface function f: tdynarray; implementation type tdynarray = array of integer; function f: tdynarray; begin end; end. === code end === Which of course does not compile.

This is not equivalent. A private type declaration in a class adds a new identifier that is visible inside that class. You then use it, still in that class, to declare the return type of a function. Next, in a scope where that type identifier is no longer visible, you call the function.

My example is a complete match to that scenario as far as identifier visibility is concerned (you use a type in a scope where it is visible to declare a function return type, and then call the function in a scope where it is not visible). In your example, the type is not visible in the place where the function is declared but only where it is defined.

Jonas

Reply by email

Xiangrong Fang
to Jonas Maebe

2013/10/30 Jonas Maebe

Show quoted text 13 lines
This is not equivalent. A private type declaration in a class adds a new identifier that is visible inside that class. You then use it, still in that class, to declare the return type of a function. Next, in a scope where that type identifier is no longer visible, you call the function. My example is a complete match to that scenario as far as identifier visibility is concerned (you use a type in a scope where it is visible to declare a function return type, and then call the function in a scope where it is not visible). In your example, the type is not visible in the place where the function is declared but only where it is defined ​.

​This is logically WRONG. Because to the machine, any function return value can be seen as an array of bytes, for example, a pointer is array[0..3] of Byte on a 32-bit machine. The purpose of type system is to explain what these bytes stands for. So, if a type is out-of-scope, how do you interpret the data?​

The current "delphi compatible" implementation IS using the type information to compile the program, i.e. although it is not visible, it is indeed used by the compile, which, in my opinion, violates visibility rules.

Standing on your view point, if a type is no longer visible, but a variable (function return value) of that type is in current scope, and understood by the program, this means, this value itself carries type information! Is is kind of meta data available in Pascal? If so, I think RTTI should work for ANY kind of primitive data types.

Regards,
Xiangrong

Reply by email

Sven Barth
to Xiangrong Fang: 2013/10/30 Jonas Maebe ​This is logically WRONG. Because to the machine, any function…
Xiangrong Fang wrote 36 lines
2013/10/30 Jonas Maebe < > This is not equivalent. A private type declaration in a class adds a new identifier that is visible inside that class. You then use it, still in that class, to declare the return type of a function. Next, in a scope where that type identifier is no longer visible, you call the function. My example is a complete match to that scenario as far as identifier visibility is concerned (you use a type in a scope where it is visible to declare a function return type, and then call the function in a scope where it is not visible). In your example, the type is not visible in the place where the function is declared but only where it is defined . This is logically WRONG. Because to the machine, any function return value can be seen as an array of bytes, for example, a pointer is array[0..3] of Byte on a 32-bit machine. The purpose of type system is to explain what these bytes stands for. So, if a type is out-of-scope, how do you interpret the data? The current "delphi compatible" implementation IS using the type information to compile the program, i.e. although it is not visible, it is indeed used by the compile, which, in my opinion, violates visibility rules. Standing on your view point, if a type is no longer visible, but a variable (function return value) of that type is in current scope, and understood by the program, this means, this value itself carries type information! Is is kind of meta data available in Pascal? If so, I think RTTI should work for ANY kind of primitive data types.

For unit interfaces there is indeed the point that if unit A uses unit B then the program which uses unit A will be able to access types used by unit A. E.g.:

=== unit A ===

unit A;
interface
type
   TTest = class
     procedure Test;
   end;
implementation
procedure TTest.Test;
begin
   Writeln('Foobar');
end;
end.

=== unit A ===

=== unit B ===

unit B;
interface
uses
   A;
function SomeTest: TTest;
implementation
function SomeTest: TTest;
begin
   Result := TTest.Create;
end;
end.

=== unit B ===

=== program ===

program test;
uses
   B;
begin
   // there won't be an error here
   SomeTest.Test;
end.

=== program ===

It's this way at least since Turbo Pascal (though without classes then ;) ).

Regards,
Sven

Reply by email

Frederic Da Vitoria
to Sven Barth

2013/10/31 Sven Barth

Show quoted text 99 lines
Am 31.10.2013 02:45, schrieb Xiangrong Fang: 2013/10/30 Jonas Maebe > > This is not equivalent. A private type declaration in a class adds a new > identifier that is visible inside that class. You then use it, still in > that class, to declare the return type of a function. Next, in a scope > where that type identifier is no longer visible, you call the function. > > My example is a complete match to that scenario as far as identifier > visibility is concerned (you use a type in a scope where it is visible to > declare a function return type, and then call the function in a scope where > it is not visible). In your example, the type is not visible in the place > where the function is declared but only where it is defined > . > This is logically WRONG. Because to the machine, any function return value can be seen as an array of bytes, for example, a pointer is array[0..3] of Byte on a 32-bit machine. The purpose of type system is to explain what these bytes stands for. So, if a type is out-of-scope, how do you interpret the data? The current "delphi compatible" implementation IS using the type information to compile the program, i.e. although it is not visible, it is indeed used by the compile, which, in my opinion, violates visibility rules. Standing on your view point, if a type is no longer visible, but a variable (function return value) of that type is in current scope, and understood by the program, this means, this value itself carries type information! Is is kind of meta data available in Pascal? If so, I think RTTI should work for ANY kind of primitive data types. For unit interfaces there is indeed the point that if unit A uses unit B then the program which uses unit A will be able to access types used by unit A. E.g.: === unit A === unit A; interface type TTest = class procedure Test; end; implementation procedure TTest.Test; begin Writeln('Foobar'); end; end. === unit A === === unit B === unit B; interface uses A; function SomeTest: TTest; implementation function SomeTest: TTest; begin Result := TTest.Create; end; end. === unit B === === program === program test; uses B; begin // there won't be an error here SomeTest.Test; end. === program === It's this way at least since Turbo Pascal (though without classes then ;) ).

Yes, I agree this is the TP/Delphi way, and as such should be kept at least in DELPHI mode. But is this really good? Doesn't this contradict the Pascal philosophy? Borland did a few questionable things (look at how you used the semicolons in you examples above ;-) ), and it took some decisions when implementing units. But how is this handled in Modula?

Frederic Da Vitoria (davitof) Membre de l'April - « promouvoir et défendre le logiciel libre » - http://www.april.org

Reply by email

Sven Barth
to Frederic Da Vitoria
Frederic Da Vitoria wrote 112 lines
2013/10/31 Sven Barth < > Am 31.10.2013 02:45, schrieb Xiangrong Fang: > 2013/10/30 Jonas Maebe < > > > > > This is not equivalent. A private type declaration in a class > adds a new identifier that is visible inside that class. You > then use it, still in that class, to declare the return type > of a function. Next, in a scope where that type identifier is > no longer visible, you call the function. > > My example is a complete match to that scenario as far as > identifier visibility is concerned (you use a type in a scope > where it is visible to declare a function return type, and > then call the function in a scope where it is not visible). > In your example, the type is not visible in the place where > the function is declared but only where it is defined > . > > > This is logically WRONG. Because to the machine, any function > return value can be seen as an array of bytes, for example, a > pointer is array[0..3] of Byte on a 32-bit machine. The purpose > of type system is to explain what these bytes stands for. So, if > a type is out-of-scope, how do you interpret the data? > > The current "delphi compatible" implementation IS using the type > information to compile the program, i.e. although it is not > visible, it is indeed used by the compile, which, in my opinion, > violates visibility rules. > > Standing on your view point, if a type is no longer visible, but > a variable (function return value) of that type is in current > scope, and understood by the program, this means, this value > itself carries type information! Is is kind of meta data > available in Pascal? If so, I think RTTI should work for ANY kind > of primitive data types. > For unit interfaces there is indeed the point that if unit A uses unit B then the program which uses unit A will be able to access types used by unit A. E.g.: === unit A === unit A; interface type TTest = class procedure Test; end; implementation procedure TTest.Test; begin Writeln('Foobar'); end; end. === unit A === === unit B === unit B; interface uses A; function SomeTest: TTest; implementation function SomeTest: TTest; begin Result := TTest.Create; end; end. === unit B === === program === program test; uses B; begin // there won't be an error here SomeTest.Test; end. === program === It's this way at least since Turbo Pascal (though without classes then ;) ). Yes, I agree this is the TP/Delphi way, and as such should be kept at least in DELPHI mode. But is this really good? Doesn't this contradict the Pascal philosophy? Borland did a few questionable things (look at how you used the semicolons in you examples above ;-) ), and it took some decisions when implementing units. But how is this handled in Modula?

Undoing this even for only non-TP/Delphi modes would mean adjusting very much code out there. So no, this is how Object Pascal works.

Regards,
Sven

Reply by email

Frederic Da Vitoria
to Sven Barth

2013/10/31 Sven Barth

Show quoted text 113 lines
Am 31.10.2013 12:38, schrieb Frederic Da Vitoria: 2013/10/31 Sven Barth > Am 31.10.2013 02:45, schrieb Xiangrong Fang: > > 2013/10/30 Jonas Maebe > >> >> This is not equivalent. A private type declaration in a class adds a >> new identifier that is visible inside that class. You then use it, still in >> that class, to declare the return type of a function. Next, in a scope >> where that type identifier is no longer visible, you call the function. >> >> My example is a complete match to that scenario as far as identifier >> visibility is concerned (you use a type in a scope where it is visible to >> declare a function return type, and then call the function in a scope where >> it is not visible). In your example, the type is not visible in the place >> where the function is declared but only where it is defined >> . >> > > This is logically WRONG. Because to the machine, any function return > value can be seen as an array of bytes, for example, a pointer is > array[0..3] of Byte on a 32-bit machine. The purpose of type system is to > explain what these bytes stands for. So, if a type is out-of-scope, how do > you interpret the data? > > The current "delphi compatible" implementation IS using the type > information to compile the program, i.e. although it is not visible, it is > indeed used by the compile, which, in my opinion, violates visibility rules. > > Standing on your view point, if a type is no longer visible, but a > variable (function return value) of that type is in current scope, and > understood by the program, this means, this value itself carries type > information! Is is kind of meta data available in Pascal? If so, I think > RTTI should work for ANY kind of primitive data types. > > For unit interfaces there is indeed the point that if unit A uses > unit B then the program which uses unit A will be able to access types used > by unit A. E.g.: > > === unit A === > > unit A; > > interface > > type > TTest = class > procedure Test; > end; > > implementation > > procedure TTest.Test; > begin > Writeln('Foobar'); > end; > > end. > > === unit A === > > === unit B === > > unit B; > > interface > > uses > A; > > function SomeTest: TTest; > > implementation > > function SomeTest: TTest; > begin > Result := TTest.Create; > end; > > end. > > === unit B === > > === program === > > program test; > > uses > B; > > begin > // there won't be an error here > SomeTest.Test; > end. > > === program === > > It's this way at least since Turbo Pascal (though without classes then ;) > ). > Yes, I agree this is the TP/Delphi way, and as such should be kept at least in DELPHI mode. But is this really good? Doesn't this contradict the Pascal philosophy? Borland did a few questionable things (look at how you used the semicolons in you examples above ;-) ), and it took some decisions when implementing units. But how is this handled in Modula? Undoing this even for only non-TP/Delphi modes would mean adjusting very much code out there. So no, this is how Object Pascal works.

Ah, you mean that this is too much intricately mixed with the compiler code and it would be much too much work to change? OK, this I understand :-)

Frederic Da Vitoria (davitof) Membre de l'April - « promouvoir et défendre le logiciel libre » - http://www.april.org

Reply by email

waldo kitty
to Frederic Da Vitoria: 2013/10/31 Sven Barth Yes, I agree this is the TP/Delphi way, and as such should be kept…
Frederic Da Vitoria wrote
2013/10/31 Sven Barth

[...]

Show quoted text 5 lines
It's this way at least since Turbo Pascal (though without classes then ;) ). Yes, I agree this is the TP/Delphi way, and as such should be kept at least in DELPHI mode.

and TP mode, of course ;)

But is this really good? Doesn't this contradict the Pascal philosophy? Borland did a few questionable things (look at how you used the semicolons in you examples above ;-) ),

i can't see anything untoward with their use... they are statement separators, after all ;)

and it took some decisions when implementing units. But how is this handled in Modula?

:)

NOTE: No off-list assistance is given without prior approval. Please keep mailing list traffic on the list unless private contact is specifically requested and granted.

Reply by email

Sven Barth
to Frederic Da Vitoria: 2013/10/31 Sven Barth Ah, you mean that this is too much intricately mixed with the…
Frederic Da Vitoria wrote 52 lines
2013/10/31 Sven Barth < > Am 31.10.2013 12:38, schrieb Frederic Da Vitoria: > 2013/10/31 Sven Barth < > > > > Am 31.10.2013 02:45, schrieb Xiangrong Fang: >> 2013/10/30 Jonas Maebe < >> > >> >> >> This is not equivalent. A private type declaration in a >> class adds a new identifier that is visible inside that >> class. You then use it, still in that class, to declare >> the return type of a function. Next, in a scope where >> that type identifier is no longer visible, you call the >> function. >> >> My example is a complete match to that scenario as far >> as identifier visibility is concerned (you use a type in >> a scope where it is visible to declare a function return >> type, and then call the function in a scope where it is >> not visible). In your example, the type is not visible >> in the place where the function is declared but only >> where it is defined >> . >> >> >> This is logically WRONG. Because to the machine, any >> function return value can be seen as an array of bytes, for >> example, a pointer is array[0..3] of Byte on a 32-bit >> machine. The purpose of type system is to explain what >> these bytes stands for. So, if a type is out-of-scope, how >> do you interpret the data? >> >> The current "delphi compatible" implementation IS using the >> type information to compile the program, i.e. although it is >> not visible, it is indeed used by the compile, which, in my >> opinion, violates visibility rules. >> >> Standing on your view point, if a type is no longer visible, >> but a variable (function return value) of that type is in >> current scope, and understood by the program, this means, >> this value itself carries type information! Is is kind of >> meta data available in Pascal? If so, I think RTTI should >> work for ANY kind of primitive data types. >> > For unit interfaces there is indeed the point that if unit A > uses unit B then the program which uses unit A will be able > to access types used by unit A. E.g.: >

...

Show quoted text 20 lines
> It's this way at least since Turbo Pascal (though without > classes then ;) ). > > > Yes, I agree this is the TP/Delphi way, and as such should be > kept at least in DELPHI mode. But is this really good? Doesn't > this contradict the Pascal philosophy? Borland did a few > questionable things (look at how you used the semicolons in you > examples above ;-) ), and it took some decisions when > implementing units. But how is this handled in Modula? Undoing this even for only non-TP/Delphi modes would mean adjusting very much code out there. So no, this is how Object Pascal works. Ah, you mean that this is too much intricately mixed with the compiler code and it would be much too much work to change? OK, this I understand :-)

It's not about being mixed with the compiler code it's about too many legacy code relying on this behavior, because it's a given since TP times.

Regartds,
Sven

Reply by email

Frederic Da Vitoria
to waldo kitty: [...] and TP mode, of course ;) i can't see anything untoward with their use... they are…

2013/10/31 waldo kitty

Show quoted text 11 lines
On 10/31/2013 7:38 AM, Frederic Da Vitoria wrote: > But is this really good? Doesn't this contradict the Pascal > philosophy? Borland did a few questionable things (look at how you used > the > semicolons in you examples above ;-) ), > i can't see anything untoward with their use... they are statement separators, after all ;)

Not when they are placed before a "end" since "end" is not a statement. Some Pascal compilers would even completely refuse a semicolon before a "end".

Frederic Da Vitoria (davitof) Membre de l'April - « promouvoir et défendre le logiciel libre » - http://www.april.org

Reply by email

Frederic Da Vitoria
to Sven Barth: ... It's not about being mixed with the compiler code it's about too many legacy code…

2013/10/31 Sven Barth

Show quoted text 68 lines
Am 31.10.2013 14:42, schrieb Frederic Da Vitoria: 2013/10/31 Sven Barth > Am 31.10.2013 12:38, schrieb Frederic Da Vitoria: > > 2013/10/31 Sven Barth > >> Am 31.10.2013 02:45, schrieb Xiangrong Fang: >> >> 2013/10/30 Jonas Maebe >> >>> >>> This is not equivalent. A private type declaration in a class adds a >>> new identifier that is visible inside that class. You then use it, still in >>> that class, to declare the return type of a function. Next, in a scope >>> where that type identifier is no longer visible, you call the function. >>> >>> My example is a complete match to that scenario as far as identifier >>> visibility is concerned (you use a type in a scope where it is visible to >>> declare a function return type, and then call the function in a scope where >>> it is not visible). In your example, the type is not visible in the place >>> where the function is declared but only where it is defined >>> . >>> >> >> This is logically WRONG. Because to the machine, any function return >> value can be seen as an array of bytes, for example, a pointer is >> array[0..3] of Byte on a 32-bit machine. The purpose of type system is to >> explain what these bytes stands for. So, if a type is out-of-scope, how do >> you interpret the data? >> >> The current "delphi compatible" implementation IS using the type >> information to compile the program, i.e. although it is not visible, it is >> indeed used by the compile, which, in my opinion, violates visibility rules. >> >> Standing on your view point, if a type is no longer visible, but a >> variable (function return value) of that type is in current scope, and >> understood by the program, this means, this value itself carries type >> information! Is is kind of meta data available in Pascal? If so, I think >> RTTI should work for ANY kind of primitive data types. >> >> For unit interfaces there is indeed the point that if unit A uses >> unit B then the program which uses unit A will be able to access types used >> by unit A. E.g.: >> > ... It's this way at least since Turbo Pascal (though without classes >> then ;) ). >> > > Yes, I agree this is the TP/Delphi way, and as such should be kept at > least in DELPHI mode. But is this really good? Doesn't this contradict the > Pascal philosophy? Borland did a few questionable things (look at how you > used the semicolons in you examples above ;-) ), and it took some decisions > when implementing units. But how is this handled in Modula? > > Undoing this even for only non-TP/Delphi modes would mean adjusting > very much code out there. So no, this is how Object Pascal works. > Ah, you mean that this is too much intricately mixed with the compiler code and it would be much too much work to change? OK, this I understand :-) It's not about being mixed with the compiler code it's about too many legacy code relying on this behavior, because it's a given since TP times.

...and this modification would only become relevant for new code, so quite probably not worth the compiler extra code. Yes, I can understand this too. But my question was not about changing the behavior of fpc (not any more). This was a theoretical question. In other words, if you had been in a position to create TP back in nineteen something, and if one of your main concerns had been about respecting the Pascal philosophy, how would you have handled this? The way it has been done? Or do you agree this was not quite orthodox (although efficient)?

Frederic Da Vitoria (davitof) Membre de l'April - « promouvoir et défendre le logiciel libre » - http://www.april.org

Reply by email

Tomas Hajny
to Frederic Da Vitoria: 2013/10/31 waldo kitty Not when they are placed before a "end" since "end" is not a…
Frederic Da Vitoria wrote 17 lines
2013/10/31 waldo kitty > On 10/31/2013 7:38 AM, Frederic Da Vitoria wrote: > >> But is this really good? Doesn't this contradict the Pascal >> philosophy? Borland did a few questionable things (look at how you used >> the >> semicolons in you examples above ;-) ), >> > > i can't see anything untoward with their use... they are statement > separators, after all ;) > Not when they are placed before a "end" since "end" is not a statement. Some Pascal compilers would even completely refuse a semicolon before a "end".

It isn't necessarily about "end" being a statement, but about allowing or not allowing empty statements:

begin
 WriteLn (1)
 ;;;;
 WriteLn (1)
end.

Tomas

Reply by email

Sven Barth
to Frederic Da Vitoria: 2013/10/31 Sven Barth ...and this modification would only become relevant for new code,…
Frederic Da Vitoria wrote 92 lines
2013/10/31 Sven Barth < > Am 31.10.2013 14:42, schrieb Frederic Da Vitoria: > 2013/10/31 Sven Barth < > > > > Am 31.10.2013 12:38, schrieb Frederic Da Vitoria: >> 2013/10/31 Sven Barth < >> > >> >> Am 31.10.2013 02:45, schrieb Xiangrong Fang: >>> 2013/10/30 Jonas Maebe < >>> > >>> >>> >>> This is not equivalent. A private type declaration >>> in a class adds a new identifier that is visible >>> inside that class. You then use it, still in that >>> class, to declare the return type of a function. >>> Next, in a scope where that type identifier is no >>> longer visible, you call the function. >>> >>> My example is a complete match to that scenario as >>> far as identifier visibility is concerned (you use >>> a type in a scope where it is visible to declare a >>> function return type, and then call the function in >>> a scope where it is not visible). In your example, >>> the type is not visible in the place where the >>> function is declared but only where it is defined >>> . >>> >>> >>> This is logically WRONG. Because to the machine, any >>> function return value can be seen as an array of bytes, >>> for example, a pointer is array[0..3] of Byte on a >>> 32-bit machine. The purpose of type system is to >>> explain what these bytes stands for. So, if a type is >>> out-of-scope, how do you interpret the data? >>> >>> The current "delphi compatible" implementation IS using >>> the type information to compile the program, i.e. >>> although it is not visible, it is indeed used by the >>> compile, which, in my opinion, violates visibility rules. >>> >>> Standing on your view point, if a type is no longer >>> visible, but a variable (function return value) of that >>> type is in current scope, and understood by the >>> program, this means, this value itself carries type >>> information! Is is kind of meta data available in >>> Pascal? If so, I think RTTI should work for ANY kind of >>> primitive data types. >>> >> For unit interfaces there is indeed the point that if >> unit A uses unit B then the program which uses unit A >> will be able to access types used by unit A. E.g.: >> ... >> It's this way at least since Turbo Pascal (though >> without classes then ;) ). >> >> >> Yes, I agree this is the TP/Delphi way, and as such should >> be kept at least in DELPHI mode. But is this really good? >> Doesn't this contradict the Pascal philosophy? Borland did a >> few questionable things (look at how you used the semicolons >> in you examples above ;-) ), and it took some decisions when >> implementing units. But how is this handled in Modula? > Undoing this even for only non-TP/Delphi modes would mean > adjusting very much code out there. So no, this is how Object > Pascal works. > > > Ah, you mean that this is too much intricately mixed with the > compiler code and it would be much too much work to change? OK, > this I understand :-) > It's not about being mixed with the compiler code it's about too many legacy code relying on this behavior, because it's a given since TP times. ...and this modification would only become relevant for new code, so quite probably not worth the compiler extra code. Yes, I can understand this too. But my question was not about changing the behavior of fpc (not any more). This was a theoretical question. In other words, if you had been in a position to create TP back in nineteen something, and if one of your main concerns had been about respecting the Pascal philosophy, how would you have handled this? The way it has been done? Or do you agree this was not quite orthodox (although efficient)?

I honestly don't know what I would have done...

Regards,
Sven

Reply by email

Martin
to Frederic Da Vitoria: 2013/10/31 Sven Barth ...and this modification would only become relevant for new code,…
Frederic Da Vitoria wrote 11 lines
...and this modification would only become relevant for new code, so quite probably not worth the compiler extra code. Yes, I can understand this too. But my question was not about changing the behavior of fpc (not any more). This was a theoretical question. In other words, if you had been in a position to create TP back in nineteen something, and if one of your main concerns had been about respecting the Pascal philosophy, how would you have handled this? The way it has been done? Or do you agree this was not quite orthodox (although efficient)?

Well, that depends on how you see a type.

If a type is something that I can use to declare a variable, then the "type-information" (for lack of another term) that is part of a typed variable is not a "type". Because I can not use it to declare a variable..

So if you differ between type, and type-information then there is no conflict.

A typed variable has type info (never mind RTTI, it may just be avail at compile time). this type info can be accessed through the variable.

---
Also where is the problem with it?
By making a variable or function's result) public, you declare, that it should be usable. So you should expect all indirect requirements to be made available too.

Reply by email