Recent

Author Topic: Immutable data types  (Read 9540 times)

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Immutable data types
« Reply #45 on: October 03, 2022, 10:06:31 pm »
And the important thing is, here I did it intentionally, but it is easy to see a situation where one person is writing a type (or typehelper) and changes the definition of one method to now alter one of the fields, while the usage, where it is assumed to be constant, is made by a different person.

Here i have to agree.

As do I, for what it's worth. However if I could throw in a recollection from years ago: I was actually at a conference, decades ago, where a somebody presented a paper describing a methodology that he was using to teach Modula-2 (described as some variant of "software hut", if memory serves). It was some variant of:

* Divide a class into teams, each with three subteams.

* Each subteam writes the definition module for part of the assignment.

* A different subteam writes the implementation module.

* The third subteam has the responsibility for integration and debugging.

The language enforced robust equivalence between implementation and definition, and the development environment prevented anybody other than the assigned subteam from changing module content.

So at the very least it's possible to say that there's precedent for having the IDE and compiler detect inconsistencies (and for LARTing students until they appreciate that the tools are trying to help rather than hinder).

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: Immutable data types
« Reply #46 on: October 03, 2022, 11:50:55 pm »
However i believe that XE3+ record helpers was abomination anyway. They failed to design proper changes to the compiler and to the type system, so they started to apply what were "ugly hacks for retroactively modifying with closed-source software" to the very foundaiton of RTL.

Whatever is dependent upon simpe type helpers is dependent upon a feature broken by design. You just made one more good case to this.
I must admit, I absolutely do not care about Delphi, I last used Delphi over a decade ago. In FreePascal type helpers (something that does not even exist in Delphi) are alive and well. But you can also change this to advanced records to make the same point.

Code: Pascal  [Select][+][-]
  1. type
  2.   TTest = record
  3.     i: Integer;
  4.     procedure Inc;
  5.   end;
  6.  
  7. procedure TTest.Inc;
  8. begin
  9.   Self.i += 1;
  10. end;
  11.  
  12. procedure Foo(const t: TTest);
  13. begin
  14.   t.Inc; // Works
  15.   t.i += 1; // Error: Can't assign values to const variable
  16. end;

If you are coming from Delphi than you might also not know about advanced records, as they are one of the newer features of freepascal, basically a newer spin on old style objects but without inheritance.

if you agree that const is - with all the holes - a useful tool to protect you from yourself, then so would be values.
The problem with const is, it is not reliable. It works if you have primitive datatypes, with no type helpers or non advanced records. But anything else can circumvent the constness. And the main concern here is not just that you can circumvent constness, because there are ways to always circumvent constness. The problem is that the constness is not propagated through, so you loose the constness in a totally different place.

Take again the type helper example from above (or the advanced record if you don't like type helpers), the constness is not lost in the function that gets the const record, it is lost in the function called on the type helper. This function is potentially in a completely different part of the code, written by a completely different person, and from your point of view as a user you can assume it to be a black box.

So you must assume that whenever you call such a method, which looses constness information, that the data could have been altered. The problem is, it only requires one hole to not be reliable anymore. As soon as any hole is introduced, the usage of the functionality with that hole will basically mean that all assumptions of validity are gone.

I wonder if you would then try to take pointer to the this->i
Okay, naive attempt would probaly fail, as you would need a "pointer to const" to take i's address (hopefully, don't want to go godbolt). But add a bit of union{...}
Yes it would be a pointer to a const. Just on a side note about union, actually according to the C standard, the behavior of accessing different fields of a union is undefined, meaning you can only read from the field that you assigned the value to. Shure most compilers simply overlay the memory, but strictly speaking you can't assume that, and the usage of unions to convert data representation is not valid C code. Same holds btw. for pointer casting between types, but you can cast away the const. Standard C does not intend for the programmer to convert between different representations of the same data (as this code is inherently unportable).

C is actually really strict in this respect, but this is a bit off topic I think.

All in all, this more fine-grained const distinction in C++ is really nice to had, but retroactively introducing it made their reverse-directin type declaration yet worse...
I don't propose this, this was just a thought experiment that if one would seriously want to have a concept of constant/assign once data, then this must be incorporated in the typesystem. That said, you can't just change the typesystem of an existing language. FreePascal with the typesystem of C or C++ would not be FreePascal anymore. So maybe this would be interesting for anyone trying to design a new language on the basis of Pascal with some new features, but it's not something that could be added into an existing language.

Arioch

  • Sr. Member
  • ****
  • Posts: 421
Re: Immutable data types
« Reply #47 on: October 04, 2022, 01:09:39 am »
In FreePascal type helpers (something that does not even exist in Delphi) are alive and well.

But you can also change this to advanced records to make the same point.

I don't see how it is the same point. You just made an incapsulated object(record) with an exlicit mutating method.
Basically, you reiterated that FPC/Delphi does not have "immutable objects" and calling any method might change the internal state.

But we all know it and we do not expect it otherwise. You called a method - you are on its mercy now.
Here is no broken expectations, at least no more than usual.

Quote
from your point of view as a user you can assume it to be a black box.

This!

=====================

On helpers I'll have to see. My current understanding (shallow glance) is that FPC type helpers is the same as Delphi record helpers just renamed. Plus, FPC does not prohibit several different helpers be active at once. And so, i did not look any deeper.

Would those be compiler intrinsics, so that no one but compiler makers could create those helpers - it would've been okay. One compiler magic more, one less, no big deal. But they are not.

With people encouraged to make their own helpers - they have either go into self-censorship, identifying this feature as dangerous, or end up having different helpers in different libraries for the same type.

So they get the unpredictability of big (actually - unit-big) WITH clause. Some place up there  far away, visibly unrelated, included some unit - and suddenly he identifiers you use in your code changed meaning. Hopefully thy would stop compiling, worse if they would compile yet change meaning.

Delphi's restriction "only one helper" pessimizes creating your own helpers for types RTL already mase helpers for. But not prohibit it.
Multiple helpers mode of FPC does not even have it.

Imagine i have two libraries, both interface database of cars, but differnent datasets: one has information for different plate numbers (as road police gathers, "instances" of cars), and other - for different models (as shops/commercials do, "classes" of cars),

While i only had one library, it was cool, fancy and fashionably pythonish.

Code: Pascal  [Select][+][-]
  1.   UsedCar := 'VX-10574-RU'.GetCar;
  2.  

Code: Pascal  [Select][+][-]
  1.   CarModel := 'Volvo X5 Black'.GetCar;
  2.  

Cuule, man, aintah?

But of course, i might want to integrate both datasets.
If my program user looks to buy a used car on esome -bay, then he would benefit from oth reading reviews of the car model, and reading "police story" about this specific instance, maybe it was into accidents.
So, i throw both units, accessing both datasets into my uses clause....

...and what does string.GetCar even mean now?

And here we go back to your earlier statement:

Quote
it is easy to see a situation where one person is writing a type (or typehelper) and changes the definition of one method to now alter one of the fields, while the usage, where it is assumed to be constant, is made by a different person

Type helpers promote sudden and global change of the working code, without actually the sources of that code being touched.

Imagine i was lucky to have a lucky sequency in my uses.

Code: Pascal  [Select][+][-]
  1. uses .... CarHistoryDB, CarMagazineReviews, ....
  2.  
  3. ....
  4.  
  5.   CarModel := 'Volvo X5 Black'.GetCar;
  6.  

Works like a charm.

Then the CarMagazineReviews library team decided they made bad name, ambiguos if not misleading. And they cheanged their helper to be publish GetReviews instead.

Oooops, suddenly my old polished ocde i did not touch for 5 years changed the meaning and (hopefully) compiles no more. But if both heplers were returning IUnknown and being fancy trendy libraries provided OLEAuto runtime-binding interface... Ooooops - it only gives "catastrophic call failure" later in the runtime.

And then there was another string helpers, that also published a function string.GetReviews - but those were reviews of parking lots for tourists.
Those calls suddenly got broken too!

 %)

Good luck with this mess...
« Last Edit: October 04, 2022, 01:17:10 am by Arioch »

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: Immutable data types
« Reply #48 on: October 04, 2022, 01:47:58 am »
I don't see how it is the same point. You just made an incapsulated object(record) with an exlicit mutating method.
Basically, you reiterated that FPC/Delphi does not have "immutable objects" and calling any method might change the internal state.

But we all know it and we do not expect it otherwise. You called a method - you are on its mercy now.
Here is no broken expectations, at least no more than usual.
Yes it broke the expectation, the parameter is declared as const, therefore the expectation is that it is immutable. But the fact that by calling a method it can be mutated is breaking this expectation. And this should not be possible. In fact, with non method functions this is actually the case:
Code: Pascal  [Select][+][-]
  1. type
  2.   TTest = record
  3.     i: Integer;
  4.     procedure Inc;
  5.   end;
  6.  
  7. procedure TTest.Inc;
  8. begin
  9.   Self.i += 1;
  10. end;
  11.  
  12. procedure IncTest(var Self: TTest);
  13. begin
  14.   Self.i += 1;
  15. end;
  16.  
  17. procedure Foo(const t: TTest);
  18. begin
  19.   t.Inc; // Works
  20.   IncTest(t); // Error: Can't assign values to const variables
  21. end;
Conceptually the method and the function should be the same, and infact they are, a method simply is a function with a hidden self var parameter as first parameter. But they work differently. The reason is that the const system works ok-ish for regular functions but does not extend to methods.

If I say that something is immutable with the const keyword, I would expect that I am not able to mutate it. The fact that I can do this, no matter if it's through a method, a function, an operator or by doing a performative dance in front of my pc, breaks this expectation. It's called "const" not "ConstUnlessYouCallAMethodOnIt", so I expect it to be constant

...and what does string.GetCar even mean now?
This is the classical diamond problem from multi inheritance. And the solution is extremely simple, throw an ambiguity error and let the user resolve it manually:
Code: Pascal  [Select][+][-]
  1. TMyHelper1(instance).Method; // Call Method from Helper1
  2. TMyHelper2(instance).Method; // Call Method from Helper2
This works for Multiinheritance in languages like C++. For type helpers specifically, these are a staple of the swift programming language, where this is also resolved similarly. This "problem" was solved decades ago.

Quote
Oooops, suddenly my old polished ocde i did not touch for 5 years changed the meaning and (hopefully) compiles no more. But if both heplers were returning IUnknown and being fancy trendy libraries provided OLEAuto runtime-binding interface... Ooooops - it only gives "catastrophic call failure" later in the runtime.
If the library you are using changes it's interface of course it effects your code. But this is not a property of type helpers, but of any function. Just imagine like:
Code: Pascal  [Select][+][-]
  1. CarModel := GetCar('Volvo X5 Black');
You have exactly the same problem. Typehelpers are just syntactic sugar, which converts functions of the form "Verb(subject, objects)" into the method form of "subject.verb(objects)". Semantically it is identical and therefore, as this is a completely non issue in the former case, it also is in the latter.

I mean yes this is actually sometimes a kindof problem when considering overloaded functions. This is exactly why C does not allow overloaded functions, but C++ does, because while the C developers see the "risk" of allowing this ambiguity to be to high, C++ doesn't. Pascal allows for overloaded functions, and this won't change probalby, so there is no reason to not allow multiple type helpers, because it's the exact same situation just with a different syntax.
« Last Edit: October 04, 2022, 01:50:47 am by Warfley »

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Immutable data types
« Reply #49 on: October 04, 2022, 08:50:39 am »
The problem with const is, it is not reliable. It works if you have primitive datatypes, with no type helpers or non advanced records. But anything else can circumvent the constness. And the main concern here is not just that you can circumvent constness, because there are ways to always circumvent constness. The problem is that the constness is not propagated through, so you loose the constness in a totally different place.

Well that's simple enough: either don't have type helpers etc. or stop calling the language Pascal.

We keep getting told "we won't implement such-and-such since it's not in the spirit of Pascal", but breaking features of the language which have been in there ab initio really is taking things too far.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: Immutable data types
« Reply #50 on: October 04, 2022, 01:29:10 pm »
We keep getting told "we won't implement such-and-such since it's not in the spirit of Pascal", but breaking features of the language which have been in there ab initio really is taking things too far.

MarkMLl
Thats actually a good point, const parameters is an original Pascal concept, long before any classes, objects, type helpers advanced records or any other form of method calling syntax. And in this setting it works fine, there still are pointers, but afaik you can't take the pointer from a const param. The problem is that when all this OOP stuff was added (i.e. objects), no one seemed to care about how constness effects those systems, and this design decision went through all the other OOP features added later.

It should also be noted that Pascal does not have a concept of constant data in general, but only constant parameters, so from this angel, a typesystem that incorporates assign once data (like C, or what was originally proposed in the first post of this thread), is not required, because there never was the intention to have constant/assign once variables in pascal to begin with.

That said, I think the current const parameter system could be improved, by simply having the compiler do a static analysis if a method can alter the state of the "self" parameter, and if this method is called on a const, either throw a warning or even an error. This would not require any changes to the language and would rule out the problems I showed above

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Immutable data types
« Reply #51 on: October 04, 2022, 02:47:39 pm »
Thats actually a good point, const parameters is an original Pascal concept, long before any classes, objects, type helpers advanced records or any other form of method calling syntax. And in this setting it works fine, there still are pointers, but afaik you can't take the pointer from a const param. The problem is that when all this OOP stuff was added (i.e. objects), no one seemed to care about how constness effects those systems, and this design decision went through all the other OOP features added later.

I was actually thinking about constant declarations at the start of a program or function (which can be broken if their address can be taken), but const parameters are obviously approximately equivalent (equivalent from the POV of semantics, if not from the memory map).

However as I pointed out earlier in either this thread or a parallel one: Object Pascal already has an inherent problem in that objects (i.e. pointers to instances of classes) are mutable even if the content of the instance is carefully protected at the semantic level.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: Immutable data types
« Reply #52 on: October 04, 2022, 03:16:37 pm »
I was actually thinking about constant declarations at the start of a program or function (which can be broken if their address can be taken), but const parameters are obviously approximately equivalent (equivalent from the POV of semantics, if not from the memory map).
Yes, but here it must be distinquished between real consts and the "writable consts" (which is a fun little oxymoron if you ask me) which are just global variables whos scope is restricted to the respective function

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Immutable data types
« Reply #53 on: October 04, 2022, 03:29:56 pm »
I was actually thinking about constant declarations at the start of a program or function (which can be broken if their address can be taken), but const parameters are obviously approximately equivalent (equivalent from the POV of semantics, if not from the memory map).
Yes, but here it must be distinquished between real consts and the "writable consts" (which is a fun little oxymoron if you ask me) which are just global variables whos scope is restricted to the respective function

Yes, agreed. But I don't think that /anybody/ really likes the "writable consts" terminology: even if they feel obliged to defend it from the POV of Borland compatibility.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: Immutable data types
« Reply #54 on: October 04, 2022, 03:41:50 pm »
My theory is that this was an april fools joke by someone at borland, who thought the name "writable constants" was a dead givaway, but nobody else noticed it and implemented it anyway.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Immutable data types
« Reply #55 on: October 04, 2022, 03:47:30 pm »
My theory is that this was an april fools joke by someone at borland, who thought the name "writable constants" was a dead givaway, but nobody else noticed it and implemented it anyway.

Borland Pascal allowed to write structured constants. Keep in mind that it was originally a 16-bit real mode compiler, and probably not as rigid due to memory limitations.

In later 16-bit PM versions, borland implemented $J to govern this, and Delphi also had a long {$writeableconst+/-} option for it.


MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Immutable data types
« Reply #56 on: October 04, 2022, 04:16:24 pm »
Borland Pascal allowed to write structured constants. Keep in mind that it was originally a 16-bit real mode compiler, and probably not as rigid due to memory limitations.

8-bit: it was in v3. "A typed constant may be used exactly like a variable of the same type".

I've got nothing against the concept, but continued use of the name in modes that don't claim to be 100% Borland-compatible is indefensible.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

lainz

  • Hero Member
  • *****
  • Posts: 4460
    • https://lainz.github.io/
Re: Immutable data types
« Reply #57 on: October 04, 2022, 04:31:18 pm »
So what's the difference between a typed constant and a var?

It's stored differently in the executable? Is faster? Is cool?

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Immutable data types
« Reply #58 on: October 04, 2022, 04:37:59 pm »
So what's the difference between a typed constant and a var?

It's stored differently in the executable? Is faster? Is cool?

If declared in a function it's persistent across function invocations. As such it behaves like a global variable but with limited scope.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

AlanTheBeast

  • Sr. Member
  • ****
  • Posts: 348
  • My software never cras....
Re: Immutable data types
« Reply #59 on: October 04, 2022, 04:49:19 pm »

As do I, for what it's worth. However if I could throw in a recollection from years ago: I was actually at a conference, decades ago, where a somebody presented a paper describing a methodology that he was using to teach Modula-2 (described as some variant of "software hut", if memory serves). It was some variant of:

* Divide a class into teams, each with three subteams.

* Each subteam writes the definition module for part of the assignment.

* A different subteam writes the implementation module.

* The third subteam has the responsibility for integration and debugging.

The language enforced robust equivalence between implementation and definition, and the development environment prevented anybody other than the assigned subteam from changing module content.

F-22 avionics integration was allegedly the least problematic of any such integration to that point.

Language:  Ada.  Companies involved trades their program interfaces ("specification") freely and clearly while keeping the implementation to themselves.  No ambiguity.

It's germane to note that between the dozens of avionics vendors on the program, the use of the internet made sure (even in those early days) that everyone had up-to-date information most of the time.  So whether there were several CSCI's in a single computer or talking across the "network" (not really, it was mainly MIL-STD-1553B).[1]

Also where " for i := 1 to 10 do .......... ;" scope limited variables could exist - despite Ada being greatly Pascal influenced.

I actually took an easy "A" class in university: Modula II - but it wasn't taught as you describe - taught the usual "you're on your own" manner.

(Took the Ada class at work).

[1]  (This wasn't the case before that - I had dozens of pre-release ARINC-429 interface descriptions for various programs that still had "author comments" all over them. These were often traded around companies as photocopies ... the h/w interface doc (429) often had higher level docs incorporated and v-v).
Everyone talks about the weather but nobody does anything about it.
..Samuel Clemens.

 

TinyPortal © 2005-2018