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!aioe.org!esY63sJc+00ALEoUyxrwTg.user.46.165.242.91.POSTED!not-for-mail From: "Dmitry A. Kazakov" Newsgroups: comp.lang.ada Subject: Re: Discriminants or Constructor Function for Limited Types Date: Sun, 8 May 2022 10:37:48 +0200 Organization: Aioe.org NNTP Server Message-ID: References: <0b4ddd38-1f19-44fe-acd9-43a316ec9d29n@googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Injection-Info: gioia.aioe.org; logging-data="5022"; posting-host="esY63sJc+00ALEoUyxrwTg.user.gioia.aioe.org"; mail-complaints-to="abuse@aioe.org"; User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Thunderbird/91.9.0 Content-Language: en-US X-Notice: Filtered by postfilter v. 0.9.2 Xref: reader02.eternal-september.org comp.lang.ada:63826 List-Id: 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. > 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. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de