Forum > FPC development
Why are types sometimes interchangeable
Joanna:
I hope it’s not too much of a bother. A non pascal using friend of mine wants to know why two identical real types he created are interchangeable. I told him that that isn’t the way to distinguish things but here is his question if anyone cares to answer.
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---{ It has come to my attention that unfortunately base data formats are conflated:} program typeDemo(input, output, stderr); type meters = real;type seconds = real; var l1: meters;var t1: seconds; begin t1 := 10.0; l1 := t1;end. {Well I didn't *want* this to compile.But OK then, this must mean Pascal uses structural typing.Therefore, two records with the same fields will be compatible:}program typeDemo(input, output, stderr); type vector = record x: real; y: real; end; type coords = record x: real; y: real; end; var v1: vector;var c1: coords; begin // there are no records initializers or what? anyway. v1.x := 10.0; v1.y := 5.0; c1 := v1;end. {Well, this time around we get nominal typing. How much more random can this type system get?}
He seems to think because two simple types are considered compatible, two records with identical fields should be compatible. How do I explain this to him? My first urge is to say something along the lines of the record fields are more hidden than the type of real.
ccrause:
--- Quote from: Joanna on January 05, 2023, 12:24:48 am ---
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---type meters = real;type seconds = real;
--- End quote ---
Here meters and seconds are declared as type aliases to the type real. Read the section on type aliases in the documentation for reference.
To create distinct new types, use the form:
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---type meters = type real;type seconds = type real;This will however still be assignment compatible types, so would not generate a compiler error when mixing these types in an expression.
440bx:
--- Quote from: Joanna on January 05, 2023, 12:24:48 am ---He seems to think because two simple types are considered compatible, two records with identical fields should be compatible. How do I explain this to him? My first urge is to say something along the lines of the record fields are more hidden than the type of real.
--- End quote ---
record fields aren't "more hidden" than anything else.
what happens in the case of
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---type meters = real;type seconds = real; var l1: meters;var t1: seconds; is that the variables l1 and t1 ultimately both resolve to "real" which is an "atomic" pre-defined type that cannot be broken down any further (unlike "meters" and "seconds", which are really just aliases for "real" as @ccrause already pointed out)
what happens in the case of
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} --- type vector = record x: real; y: real; end; type coords = record x: real; y: real; end; var v1: vector;var c1: coords; is that the types "vector" and "coords" are themselves atomic by virtue of being records. A record type definition always defines an atomic type (as in the case of "vector", "coord" or whatever other name is assigned to the type)
When the parser sees that "v1" is of type "vector" and "c1" is of type " coords", it does NOT care that the fields that make up both records are the same, that is completely irrelevant. As far as the parser is concerned, there is a type named "vector" and another type named "coords", because these are records, the different names, which implies different types, means the types are not compatible. For type identification purposes, "vector" and "coords" are atomic and as different as "integer" is from "string" is from "set" is from an enumeration, etc, etc.
succinctly, the type of a record isn't determined by the fields it contains but by its name (which is effectively the name of a new type that is assignment compatible only with itself.)
HTH.
Joanna:
--- Quote --- Here meters and seconds are declared as type aliases to the type real.
--- End quote ---
Exactly, that’s what I thought when I first saw them, of course they are the same type because they are both type real by different names. 8)
--- Quote --- the variables l1 and t1 ultimately both resolve to "real" which is an "atomic" pre-defined type that cannot be broken down any further.
the types "vector" and "coords" are themselves atomic by virtue of being records
--- End quote ---
I was not familiar with the term atomic before. Thanks for teaching me something new today. I didn’t know the correct terminology to use for this.
MarkMLl:
I've been trying, without success, to find a remark from PascalDragon when I was complaining about something-or-other a few weeks ago. Basically, his point was that there were certain number-like types that the compiler automatically treated as compatible (i.e. a byte can be assigned to a word and so on), but this didn't extend to programmer-defined types.
Hence I think it's reasonable to say that even if (from OP) meters were single and seconds were double, they would probably be compatible. Whether this is a Good Thing is arguable: it's very convenient in terms of having Pascal be a general-purpose application language, but detracts from Pascal's claim to be suitable for maximally-robust code.
I'd add that I'm not entirely happy with the term "atomic" used earlier in this thread. It's usually applied to /operations/ rather than /types/, so one would refer to a debit-this-and-credit-that operation being atomic in commerce, or a 64-bit increment being atomic if it were resistant to being broken into (by an interrupt or second CPU) when half-completed.
MarkMLl
Navigation
[0] Message Index
[#] Next page