!standard 13.13.1(9/5) 19-04-09 AI12-0329-1/02 !standard 13.13.1(9.1/5) !class Amendment 19-04-05 !status ARG Approved 9-0-2 19-04-09 !status work item 19-04-05 !status received 19-04-03 !priority Low !difficulty Easy !subject Naming of FIFO_Streams packages !summary The package family is named Storage, with children Unbounded and Bounded. The abstract type is named Storage_Stream_Type. !problem The FIFO_Streams packages seem misnamed: (1) There's nothing about the interface that limits it to FIFO operations. It *is* limited to in-memory operations, so perhaps that property should be emphasized with the name. Additionally, a Stream is inherently FIFO, so its weird to emphasize that property. (2) The use of Unbounded_ is inconsistent with the names used for the containers. (3) Repeating "Streams" in the package names is also inconsistent with the containers (we don't have packages "Vector_Container" and "Tree_Container"). Also, the type FIFO_Stream is inconsistent with the naming of other language-defined stream types, which all end with "Stream_Type". !proposal (See Summary.) !wording The root package of this subsystem is called Ada.Streams.Storage with a type Storage_Stream_Type There are two child packages, Ada.Streams.Storage.Unbounded and Ada.Streams.Storage.Bounded. The type names in the children are not changed; they remain Stream_Type. See !corrigendum below for the detailed wording changes. !discussion "Unbounded_String" is an exception to the meta-rule that we don't use "Unbounded" in names, but that clearly couldn't have been called "String", so some other name was required. We orginally proposed: Ada.Streams.Storage Storage_Stream_Type Ada.Streams.Storage.FIFO Stream_Type Ada.Streams.Storage.Bounded_FIFO Stream_Type But that was ultimately rejected as a stream is inherently FIFO, so that also is redundant information. Once we drop that, we have no name for the concrete child implementation level at all. It doesn't add anything, since the parent defines the necessary details. Thus, we dropped back to the Unbounded and Bounded names without any qualification. Ideally, the names chosen for language-defined packages would work well for both the use-adverse and the use-lovers of the Ada community. Note that everyone has to write the full expanded package name in the context clause, so shorter, less redundant names help everyone. It does pay to repeat some information in the type names, as use-lovers will not have any context to make the name clear. E-Mail discussions seemed to settle on naming this family of packages "Storage" in some way, based on the existing Storage_IO package. We also need to consider the type names, particularly of the abstract type. Some people preferred to repeat Stream in each of the package names. Your author thinks this is rather redundant (he's sick and tired of having to write Ada.Strings.Unbounded_Strings.Unbounded_String, and this would be worse), but for the record: Ada.Streams.Storage_Streams Storage_Stream_Type Ada.Streams.Storage_Streams.FIFO_Streams Stream_Type Ada.Streams.Storage_Streams.Bounded_FIFO_Streams Stream_Type We also considered "Buffers" rather than "Storage" (but Ada already uses "Storage" for this use), !corrigendum 13.13.1(9) @dinsa The Write operation appends Item to the specified stream. @dinss Three additional packages provide stream implementations that do not make use of any file operations. These packages provide the same operations, with Streams.Storage providing an abstract interface, and two child packages providing implementations of that interface. The difference is that for Streams.Storage.Bounded, the maximum storage is bounded. The library package Ada.Streams.Storage has the following declaration: @xcode<@b Ada.Streams.Storage @b Pure, Nonblocking @b> @xcode< @b Storage_Stream_Type @b Root_Stream_Type @b;> @xcode< @b Element_Count (Stream : Storage_Stream_Type) @b Stream_Element_Count @b;> @xcode< @b Clear (Stream : @b Storage_Stream_Type) @b;> @xcode<@b ... -- @ft<@i> @b Ada.Streams.Storage;> The library package Ada.Streams.Storage.Unbounded has the following declaration: @xcode<@b Ada.Streams.Storage.Unbounded @b Prelaborated, Nonblocking @b> @xcode< @b Stream_Type @b Storage_Stream_Type @b @b Default_Initial_Condition =@> Element_Count (Stream_Type) = 0;> @xcode< @b @b Read ( Stream : @b Stream_Type; Item : @b Stream_Element_Array; Last : @b Stream_Element_Offset) @b Post =@> (@b Num_Read : @b Stream_Element_Count := Stream_Element_Count'Min (Element_Count(Stream)'Old, Item'Length); @b Last = Num_Read + Item'First - 1 @b Element_Count (Stream) = Element_Count (Stream)'Old - Num_Read);> @xcode< @b @b Write ( Stream : @b Stream_Type; Item : @b Stream_Element_Array) @b Post =@> Element_Count (Stream) = Element_Count (Stream)'Old + Item'Length;> @xcode< @b @b Element_Count (Stream : Stream_Type) @b Stream_Element_Count;> @xcode< @b @b Clear (Stream : @b Stream_Type) @b Post =@> Element_Count (Stream) = 0;> @xcode<@b ... -- @ft<@i> @b Ada.Streams.Storage.Unbounded;> The library package Ada.Streams.Storage.Bounded has the following declaration: @xcode<@b Ada.Streams.Storage.Bounded @b Pure, Nonblocking @b> @xcode< @b Stream_Type (Max_Elements : Stream_Element_Count) @b Storage_Stream_Type @b @b Default_Initial_Condition =@> Element_Count (Stream_Type) = 0;> @xcode< @b @b Read ( Stream : @b Stream_Type; Item : @b Stream_Element_Array; Last : @b Stream_Element_Offset) @b Post =@> (@b Num_Read : @b Stream_Element_Count := Stream_Element_Count'Min (Element_Count(Stream)'Old, Item'Length); @b Last = Num_Read + Item'First - 1 @b Element_Count (Stream) = Element_Count (Stream)'Old - Num_Read);> @xcode< @b @b Write ( Stream : @b Stream_Type; Item : @b Stream_Element_Array) @b Pre =@> Element_Count (Stream) + Item'Length <= Stream.Max_Elements @b (@b Constraint_Error), Post =@> Element_Count (Stream) = Element_Count (Stream)'Old + Item'Length;> @xcode< @b @b Element_Count (Stream : Stream_Type) @b Stream_Element_Count @b Post =@> Element_Count'Result <= Stream.Max_Elements;> @xcode< @b @b Clear (Stream : @b Stream_Type) @b Post =@> Element_Count (Stream) = 0;> @xcode<@b ... -- @ft<@i> @b Ada.Streams.Storage.Bounded;> The Element_Count functions return the number of stream elements that are available for reading from the given stream. The Read and Write procedures behave as described for package Ada.Streams above. Stream elements are read in FIFO (first-in, first-out) order; stream elements are available for reading immediately after they are written. The Clear procedures remove any available stream elements from the given stream. !corrigendum 13.13.1(9.1/1) @dinsa If Stream_Element'Size is not a multiple of System.Storage_Unit, then the components of Stream_Element_Array need not be aliased. @dinst @s8<@i> Streams.Storage.Bounded.Stream_Type objects should be implemented without implicit pointers or dynamic allocation. !ASIS No change is needed. !ACATS test Any tests for the original AI (AI12-0293-1) would apply here as well. !appendix From: Randy Brukardt Sent: Wednesday, April 3, 2019 1:43 AM Brad's AARM Review says: 13.13.1 (12/5) package Ada.Streams.FIFO_Streams I don't see why the same interface couldn't be used for other types of streams, such as LIFO_Streams. This suggests to me that the top-level abstract package is misnamed. I think it would be much better to name the package as; package Ada.Streams.Stream_Buffers or even better just as package Ada.Streams.Buffers which better captures that these streams are in-memory buffers (without file operations). This truly is a restriction of the package, since the package is Nonblocking and cant be derived to be a Nonblocking=>False package, which would be needed to support file operations. The FIFO property of the interface is just in-name only, since anyone could derive from these packages to create abstractions that are non-FIFO. Then the two child packages could be named more specifically for FIFO semantics package Ada.Streams.Buffers.Bounded_FIFO_Streams and package Ada.Streams.Buffers.FIFO_Streams Which also is more consistent with the naming of the container packages, eg Bounded_Vectors, rather than just Bounded or Unbounded. Also, we dont typically name packages with "Unbounded", there is no Unbounded_Vectors package, so with this renaming, we could remove "Unbounded" from the package name, to also be more consistent with the Ada Containers. ================================== Generally, we don't revisit settled naming decisions. However, Brad makes some good points about the naming (especially about the generality of the base interface, and about the inconsistency with the naming of the containers). I also admit that I've never felt that we had the right names for these packages, but I've stayed silent mainly because I don't have a better alternative. But now is the time to consider if different names would be better, as it will be too late before long. As such, I'd like to take a poll to see if there is any will to discuss the names of these package again. The package names in the advisory list came from the ARG meeting where these names were chosen. It wouldn't surprise me if we ended up with some combination of names if we actually do discuss this. [Editor's note: The actual poll and voting results are not provided here.] **************************************************************** From: Randy Brukardt Sent: Wednesday, April 3, 2019 1:43 AM > Comments: [on the poll ballot - Editor.] Given that all of these packages are under "Streams", there isn't any need for the individual child names to include "Streams". Indeed, that's almost certain to be redundant noise. Even people who *love* use clauses have to give the entire name in the with clause and the use clause. And no one wants to write streams 3 or 4 times! In particular, the vast majority of units will with only one of these packages, so the intermediate names don't matter much. Someone could "use" Ada.Streams and then use the intermediate names in use clauses, I guess, but there wouldn't be much point (why save a handful of characters and make your program harder to understand?). Thus, I prefer relatively short names are every level. For me, who would hardly ever "use" one of these packages, the less redundancy in the full name the better: My_Buffer : Ada.Streams.FIFO_Streams.Unbounded.Stream_Type; -- Current name: 3 Streams. My_Buffer : Ada.Streams.Storage.FIFO.Stream_Type; -- My write-in: 2 streams. My_Buffer : Ada.Streams.Buffers.FIFO_Streams.Stream_Type; -- Brad's name: 3 streams. **************************************************************** From: Steve Baird Sent: Wednesday, April 3, 2019 5:42 PM > Comments: [on the poll ballot - Editor.] These comments may serve mostly as a reminder of why we don't want to reopen this discussion, but I'll press on nonetheless. I agree with Brad that FIFO belongs as part of the names of the concrete packages, not as part of the name of the package that defines the abstract type. The thing that distinguishes the abstract type from its parent is the addition of the Element_Count operation (and the less important Clear operation), so I feel that Counted_Streams makes sense for that package. It's been suggested that we want a name that indicates that no file operations are involved, but (as with the FIFO property) that isn't at all implied by the abstract interface and does not make sense for naming the package that declares the abstract type. Thus, I don't like any of the Buffered_Streams or Storage_Streams proposals. So I am left with only my write-in candidate to vote for. There is more to this than changing the names of the packages: we have to look at the names of the stream types too. It wouldn't make sense, for example, to have a type Ada.Streams.Buffers.FIFO_Stream which is what we would get if all we change is the package name. So we really need a proposal for 3 package names and 3 stream type names . I don't like type names that end in "_Type" (e.g., Stream_Type), but just naming all the types "Stream_Type" is an option. We have formal parameters named "Stream", so we don't want to use that name. I often like plural package names where the package exports a type with a corresponding singular name, as in package Miniature_Cars is type Car is private; ... end Miniature_Cars; or package Horses is type Horse is private; ...; end Horses; So with the package names proposed above, the type names could be Counted_Streams.Counted_Stream Counted_Streams.FIFO_Streams.FIFO_Stream Counted_Streams.Bounded_FIFO_Streams.FIFO_Stream (this proposal follows the example of Vectors and Bounded_Vectors with respect to using the same type name in the bounded and unbounded versions). **************************************************************** From: Randy Brukardt Sent: Wednesday, April 3, 2019 6:13 PM ... >It's been suggested that we want a name that indicates that no file >operations are involved, but (as with the FIFO property) that isn't at >all implied by the abstract interface ... As Brad pointed, it *is* implied by the contracts, which surely are part of the abstract interface. So I tend to disagree on this one. If we decided to change the contracts so that external (blocking) stuff was allowed, then I'd have more sympathy. (There's really no reason that the abstract stream has to be Nonblocking; that's only a requirement of actual packages. Unless you think that someone is going to try (in a nonblocking context) to dispatch through this interface rather than directly binding to the primitives of the specific types -- which seems silly for performance reasons alone.) ... > There is more to this than changing the names of the > packages: we have to look at the names of the stream types too. It > wouldn't make sense, for example, to have a type > Ada.Streams.Buffers.FIFO_Stream > which is what we would get if all we change is the package name. Agreed. I didn't realize that this was even the name of a type, it's clearly wrong regardless of any package naming. I suspect that I forgot to change that name with the others. All other existing streams end with "_Stream_Type" (or are just "Stream_Type"), and consistency alone would say that it should at a minimum be "FIFO_Stream_Type". > So we really need a proposal for 3 package names and 3 stream type > names . I don't like type names that end in "_Type" > (e.g., Stream_Type), but just naming all the types "Stream_Type" is an > option. We have formal parameters named "Stream", so we don't want to > use that name. I understand some people have this perspective, and they should do whatever makes sense for their code in their code, but for the language-defined libraries, I think it is pretty important that we consistently use names. The basic stream type is "Root_Stream_Type", and I'd argue that anything derived from it in the language should be named in a similar style. ... > So with the package names proposed above, the type names could be > Counted_Streams.Counted_Stream > Counted_Streams.FIFO_Streams.FIFO_Stream > Counted_Streams.Bounded_FIFO_Streams.FIFO_Stream I would score these at about a -200. Containing a form of "Stream" four times is madness. Remember that one is going to have to use the full name of the package in a context clause, so you would have something like: with Ada.Streams.Counted_Streams.Bounded_FIFO_Streams; which mentions Streams at least two more times than necessary! The primary reason I would like to reconsider these names is to avoid this madness, not make it worse. **************************************************************** From: Steve Baird Sent: Wednesday, April 3, 2019 6:33 PM > As Brad pointed, it*is* implied by the contracts, which surely are > part of the abstract interface. So I tend to disagree on this one. If > we decided to change the contracts so that external (blocking) stuff > was allowed, then I'd have more sympathy. Good point. So I withdraw my objection to Buffered_Streams. > The basic stream type is "Root_Stream_Type", and I'd argue that > anything derived from it in the language should be named in a similar style. Fair enough. I can live with naming all three types "Stream_Type" (or perhaps FIFO_Stream_Type for the two concrete types; what really matters is that the two should be the same). **************************************************************** From: Richard Wai Sent: Wednesday, April 3, 2019 10:41 PM I note that "storage" has a very clear meaning in Ada, and is also used for very similar ends as a FIFO in the package Ada.Storage_IO. For this reason I strongly agree with Storage_Streams.FIFO and family. The "buffer" terminology is common in the broader computing community, but I think using that here will only blur existing consistency. I for one am a huge proponent of orthogonality. I think the existence of Storage_IO especially makes the case for Storage_Streams. I think the FIFO distinction needs to be kept, because LIFO buffers have their use, as do circular buffers. So simply calling them "Storage_Streams.Unbounded" seems too ambiguous. It should be clear exactly what effect any given Write has on a subsequent Read. I also second the others who commented that the unbounded package is usually the parent of the bounded, and the unbounded is the "original". On a more technical note, it would make a lot of sense to implement these kinds of stream objects with some form of a Storage Pool, which makes the Storage name even more relevant. At the end of the day, we're going to be dealing with Storage_Elements as part-in-parcel of using the Streams "subsystem". **************************************************************** From: Tucker Taft Sent: Wednesday, April 3, 2019 11:55 PM I would agree that "Storage" is better than "Buffer" given the existing Storage_IO. I don't have time to do the full ballot at the moment, and am willing to let Randy and Steve make the decision. **************************************************************** From: Erhard Ploedereder Sent: Friday, April 5, 2019 4:07 AM Some comments: re: parent pkg Buffers. What other child packes are planned for the near future? If none, this is bad; if so, this is good. re: FIFO and queues. I expect that a queue is always FIFO or , such as priority-ordered. A LIFO queue is a stack and hence completely misnamed. So, I doubt the need for the FIFO qualification. Consistency across libraries is important. **************************************************************** From: Brad Moore Sent: Friday, April 5, 2019 9:45 AM > Comments: [on the poll ballot - Editor.] Given that we already have Storage_IO, the Storage_Streams suggestion stands out above all the others, in my mind, while addressing my original concerns. **************************************************************** From: Jeff Cousins Sent: Friday, April 5, 2019 3:14 PM > Comments: [on the poll ballot - Editor.] Though I’m sure Randy and Steve would come up with something sensible. ****************************************************************