From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on ip-172-31-65-14.ec2.internal X-Spam-Level: X-Spam-Status: No, score=-1.9 required=3.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.6 Path: eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail From: Doctor Who Newsgroups: comp.lang.ada Subject: Re: Discriminants or Constructor Function for Limited Types Date: Sun, 08 May 2022 19:19:18 +0200 Organization: A noiseless patient Spider Message-ID: <7puf7h59k2e2ns66918i95s847na2b8num@4ax.com> References: <0b4ddd38-1f19-44fe-acd9-43a316ec9d29n@googlegroups.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Injection-Info: reader02.eternal-september.org; posting-host="e9dfb6b3e1825ca64202be08946ad82b"; logging-data="11788"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/ZOjCXOzJ8P33p6LsswiDo" User-Agent: ForteAgent/8.00.32.1272 Cancel-Lock: sha1:loUz0JrKKFJLWhLgsgGFpKlP150= Xref: reader02.eternal-september.org comp.lang.ada:63828 List-Id: On Sun, 8 May 2022 10:37:48 +0200, "Dmitry A. Kazakov" wrote: >On 2022-05-08 04:32, Randy Brukardt wrote: >> "Dmitry A. Kazakov" wrote in message >> news:t5619r$10bc$1@gioia.aioe.org... >>> On 2022-05-07 05:26, Randy Brukardt wrote: >>>> "Dmitry A. Kazakov" wrote in message >>>> news:t52nd4$vj2$1@gioia.aioe.org... >>> >>>>> Because the task type is not composable. >>>> >>>> Irrelevant. A task can only be safe if it never interacts with no other >>>> objects outside of itself. >>> >>> Not when other objects are tasks, protected objects, active objects, >>> atomic objects. >> >> That's a common fallacy. Such objects are safe only if there is exactly one >> in your system. If there is more than one, various forms of failure are >> possible even if everything is supposely safe by itself. To make them fully >> safe, you have to have strong access ordering (for instance, the onion skin >> model), which no programming language and probably no static tool can >> enforce. (Proof of safety requires verification that no possible program >> flow can cause a race condition.) > >You are talking about a very low level and tightly coupled design. >Higher level object is supposed to prevent that so that there would be >no need in taking several mutexes or in chains of external entry calls, >at least not explicitly. So an active object is entirely safe. > >Anyway, we do not discuss safety of using objects, we discuss safety of >composing new objects out of existing ones. It would be silly to argue >that since Positive is unsafe due to existence of the unary minus >operation, it shall not be used a component of a record type. > >>> Because the language lacks obvious abstractions like user-defined >>> discriminants. Otherwise I see no logical reason why: >>> >>> F : File_Type ("My_Ada_file.adb"); >>> >>> should not work. >> >> It does "work", but such designs put major restrictions on your clients. > >No, you cannot have this syntax. At best you must use Pickwickian >pseudo-functions: > > F : File_Type := Open ("My_Ada_file.adb"); > >> A common way my programs are structured is something like: >> >> declare >> Output_File : Some_File_Type; >> begin >> Create_or_Open_Output (Output_File); >> Write_Output (Output_File, Data); >> ... >> Close_Output (Output_File); >> end; >> >> You can't use such a structure with your design, because you can't pass in >> the unopened file object to open it appropriately (which can take multiple >> attempts depending upon options, > >It is surprisingly easy when the type system is used as it should be. >Just derive a new type from Some_File_Type and provide a new constructor >for it. > >Note, that your code is already unsafe because nobody knows if >Create_or_Open_Output always opens the file and because there is no >guarantee that the file is closed, while the design > > declare > Output_File : Some_File_Type; > begin > Write_Output (Output_File, Data); > end; > >is 100% safe. Not in the case that your data space is exhausted, in that case Write_Output will fail, because you have no checks of free space before writing. >> Discriminants are only useful for memory management (to size arrays, to make >> components conditional). Other uses are purely mistakes. > >Nope. Discriminant is a parameter, the semantic of must be up to the >programmer. The problem with Ada is that it enforces a certain extremely >limited implementation of discriminants, so that even that limited use >you claimed is actually incorrect: > > type X (Size : Natural) is record > S : String (1..Size + 1); -- Tell me about memory management! > end record; > >>> I simplified creating the object by removing states when the object is >>> unusable for no other reason than language design. Cases when the file can >>> be unreadable because of I/O errors have nothing to do with the case when >>> the programmer did not open it. >> >> There is no difference between the state of an object before it is opened >> and the one it is in after it is closed. (And these aren't just error cases, >> as noted by the Windows example.) > >Surely, in the design where you deal with open files only, you could not >explicitly close one. The object does not have these states. Compare it >with Ada 83's Standard_Input. You are not supposed to open or close it. > >>>> We initially trying designing Claw Window objects that way, but one had >>>> to >>>> handle the case where the user clicks the 'X' (close button) while a >>>> routine >>>> is working on the window. Windows closes the window almost immediately, >>>> and >>>> the GUI library has to deal with the consequences. >>> >>> Windows sends WM_CLOSE first. >> >> Sure, but the only thing you can do at that point is make the object >> invalid. > >That is crude. > >It depends on the design but normally Windowed GUI objects are allocated >on the stack and are blocking. So WM_CLOSE should simply make an exit >from some hidden loop in something like: > > declare > Dialog : Dialog_Box; > begin > Dialog.Run; -- Note, ugliness of lacking constructors again! > >Non-modal stuff is a part of some container and thus WM_CLOSE must go to >the parent which then explicitly kills the child object. No problem. > >You do not need half-backed objects even in GUI. Such states can be >hidden in most cases. > >>>> There's little point in obsessing about designs that only work in >>>> academic >>>> exercises. Ada tries too hard already to accomadate designs like yours. >>> >>> On the contrary, it is a very practical software design problem to reduce >>> error sources as much as possible. >> >> An imaginary reduction of errors, since you have the same states that occur >> in other usage scenarios. > >No they do not. The goal is to eliminate non-functional states. Things >like closed file, uninitialized variable, null pointer etc are artifacts >of the design. There is nothing in the physical world that requires them.