From mboxrd@z Thu Jan 1 00:00:00 1970 Path: eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: "Randy Brukardt" Newsgroups: comp.lang.ada Subject: Re: Map iteration and modification Date: Wed, 3 Jan 2024 22:07:30 -0600 Organization: A noiseless patient Spider Message-ID: References: Injection-Date: Thu, 4 Jan 2024 04:06:36 -0000 (UTC) Injection-Info: dont-email.me; posting-host="369de39bb3b248004d8e62c851596a7d"; logging-data="3732299"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18Ynkjte2ZaX6Xtx5J52g0ngM+IDB48/0I=" Cancel-Lock: sha1:FbIk+yOOLs6oHoKLMgTA+RHkASQ= X-RFC2646: Format=Flowed; Response X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 6.00.2900.5931 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.7246 X-Priority: 3 Xref: news.eternal-september.org comp.lang.ada:65959 List-Id: "Dmitry A. Kazakov" wrote in message news:un3bg9$35mhv$1@dont-email.me... > On 2024-01-03 04:15, Randy Brukardt wrote: >> "Dmitry A. Kazakov" wrote in message >> news:umotm2$18lqm$1@dont-email.me... ... > The meaning of the word "iterate" is doing something (e.g. visiting an > element) again. That *is* an order. The order is an artifact. One logically visits all of the elements at the same time (certainly in an unordered container like a general map). >> Indeed, logically, all of >> the elements are presented at the same time (and parallel iteration >> provides >> an approximation of that). > > Parallel iteration changes nothing because involved tasks are enumerated > and thus ordered as well. Nonsense. There is no interface in Ada to access logical threads (the ones created by the parallel keyword). >> If you try to enforce an order on things that don't require it, you end >> up >> preventing useful parallelism (practically, at least, no one has >> succeeded >> at providing useful parallelism to sequential code and people have been >> trying for about 50 years -- they were trying when I was a university >> student in the late 1970s). > > Ordering things does not prevent parallelism. Yes it does, because it adds unnecessary constraints. It's those constraints that make parallelizing normal sequenatial code hard. A parallelizer has to guess which ones are fundamental to the code meaning and which ones are not. ... >> Ordering is a separate concept, not always >> needed (certainly not in basic structures like maps, sets, and bags). > > Right. But no ordering means no iteration, no foreach etc. If I can > iterate, that I can create an ordered set of (counter, element) pairs. > Done. > >>> Yes position is a property of enumeration. >> >> Surely not. This is a basis for my disagrement with you here. > > Then you are disagreeing with core mathematics... (:-)) You are adding an unnecessary property to the concept of iteration. Iteration does not necessarily imply enumeration (it can, of course). Iteration /= enumeration. ... >> The order is >> an artifact of doing it an inherently parallel operation sequentally. > > Yes, ordering is an ability to enumerate elements of a set. It is not an > artifact it is the sole semantics of. Iteration is not necessarily enumeration. It is applying an operation to all elements, and doing that does not require an order. Some specific operations might require an order, and clearly for those one needs to use a data structure that inherently has an order. ... >> So long as you are using arrays, you are using referential semantics. The >> only way to avoid it is to directly embed an object directly in an >> enclosing >> object (as in a record), and that doesn't work for many problems. > > The key difference is that index does not refer any element. It is > container + index that do. That's not a "key difference". That exactly how one should use cursors, especially in Ada 2022. The Ada containers do have cursor-only operations, but those should be avoided since it is impossible to provide useful contracts for those operations (the container is unknown, so the world can be modified, which is bad for parallelism and understanding). Best to consider those operations obsolete. (Note that I was *always* against the cursor-only operations in the containers.) So, using a cursor implies calling an operation that includes the container of its parameter. > From the programming POV it is about avoiding hidden states when you try > to sweep the container part under the rug. That's easily avoided -- don't use the obsolete operations. (And a style tool like Jean-Pierre's can enforce that for you.) >>> I don't see anything that is not already there. What are reasons for not >>> providing: >>> >>> M (n) [ e.g. M (n).Key, M (n).Value ] >>> M (n1..n2) [ in mutable contexts too ] >>> M'First >>> M'Last >>> M1 & M2 [ M1 or M2 ] >>> >>> They are all well-defined and useful operations. >> >> Performance. > > Irrelevant so long it does not tamper implementations of other operations. Exactly. These operations, especially slicing, have a huge impact on the cost of parameter passing for arrays (whether or not they are used). And that's a pretty fundamental operation. >> If all of these things are user-definable, then one has to use >> subprogram calls to implement all of them. That can be very expensive, >> particularly in the case of mutable operations (and mutable slices are >> the >> worst of all). > > But better, faster, safer when implemented ad-hoc by the programmer? As with all programming problems, you can only have two of the three. ;-) If the underlying programming language is already better and safer, that extends to user-written operations. (If it doesn't, it is a failure.) ... ... >> I think it is much better to get rid of most of these operations as >> built-in >> things and just let the programmer build their own operations as needed. > > Well, if you'd proposed throwing containers out the standard library I > would believe that you believe in that... (:-)) The standard library is not part of the programming language. It's a necessary adjunct, but it could be completely replaced without changing the language at all. It's necessary mainly so that basic operations are provided in the same way by all implementations, but there is little requirement to use it. Specifically, the containers are separate from Ada. Plenty of programmers use their own container libraries, with different performance and safety profiles. That's expected and intended. There is no one-size-fits-all (or even one-size-fits-many) container library. >> That keeps the cost confined to those who use them. Distributed overhead >> is >> the worst kind, and slices in particular have a boatload of that >> overhead. > > Usability always trumps performance. That's the philosophy of languages like Python, not Ada. If you truly believe this, then you shouldn't be using Ada at all, since it makes lots of compromises to usability in order to get performance. > And again, looking at the standard containers and all these *tagged* > *intermediate* objects one needs in order to do elementary things, I kind > of in doubts... (:-)) The standard containers were designed to make *safe* containers with decent performance. As I noted, they're not a built-in part of the programming language, and as such have no impact on the performance of the language proper. One could easily replace them with an unsafe design to get maximum performance -- but that would have to return pointers to elements, and you've said you don't like referential semantics. So you would never use those. You also can avoid all of the "tagged objects" (really controlled objects) by using function Element to get a copy of the element rather than some sort of reference to it. That's preferred if it doesn't cost too much for your application. Randy.