From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,21960280f1d61e84 X-Google-Attributes: gid103376,public X-Google-Language: ENGLISH,ASCII-7-bit Newsgroups: comp.lang.ada Subject: Re: How come Ada isn't more popular? References: <1169636785.504223.139630@j27g2000cwj.googlegroups.com> <45b8361a_5@news.bluewin.ch> <3pejpgfbki.fsf@hod.lan.m-e-leypold.de> From: Markus E Leypold Organization: N/A Date: Tue, 06 Feb 2007 12:45:20 +0100 Message-ID: User-Agent: Some cool user agent (SCUG) Cancel-Lock: sha1:a8ruju41kpmEajfgtR8Y4JXGmnA= MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii NNTP-Posting-Host: 88.72.224.62 X-Trace: news.arcor-ip.de 1170762016 88.72.224.62 (6 Feb 2007 12:40:16 +0200) X-Complaints-To: abuse@arcor-ip.de Path: g2news2.google.com!news3.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsfeed.arcor-ip.de!news.arcor-ip.de!not-for-mail Xref: g2news2.google.com comp.lang.ada:9021 Date: 2007-02-06T12:45:20+01:00 List-Id: Maciej Sobczak writes: >> I think the absence of manual memory management code actually >> furthers >> clarity. > > I believe so. And I stress again - GC is not the only solution for > manual memory management. OK. I accept that for the moment. I'm just not convinced you can do everything you need with scope bound memory and if you introduce manual MM again, you'll be back to confusing manual memory management. I say this just to restate my point of view clearly once again -- not that I think that either of us can prove his position at the moment. >>> Being able to just drop things on the floor is a nice feature when >>> considered in isolation, but not necessarily compatible with other >>> objectives that must be met at the same time. >> Which? > > Determinism in both timing and resource consumption? Which brings me back to what I said repeatedly to other people: (1) That this determinism is very often not a requirement (outside of embdedded programming) (2) The determinism is shot anyway by using a heap, not by using GC. Even better: GC can introduce detereminism in space consumption by compacting the heap, which naive heaps with manual MM don't do because of fragementation. (3) What is often needed are upper limits not determinism and thos upper limits can be guaranteed with GC or with an appropriate collector. >>>> People who don't have GC often say that they can do anything with >>>> manual memory management. >>> And I say that this is misconception. Good. :-) >>> Ada this point is spelled [Limited_]Controlled (it's a complete mess, >>> but that's not the fault of the concept) and in C++ it's spelled >>> automatic storage duration. >> My impression was that Ada Controlled storage is actually quite a >> clean concept compared to C++ storage duration. > Clean? It adds tag to the type, which then becomes a controlling type > in every primitive operation. > I got bitten by this recently. Adding a destructor to C++ class > never has any side effects like this. I understand. But the Ada OO way is peculiar, but not unmanagable. > Apart from this, the bare existence of *two* base types Controlled and > Limited_Controlled means that the concepts of controlled and limited > are not really orthogonal in the sense that adding one of these > meta-properties affects the interface that is "shared" by the other > aspect. Still. Being able to add a Finalize means you need to have a tagged type. I see no alternative. > It's a mess. Actually, it prevents me from thinking clearly about what > I want to achieve. Wow. > >> But both tie allocation to program scope, synchronous with a stack. I >> insist that is not always desirable: It rules out some architecture, >> especially those where OO abounds. > > What architecture? I already say in another post: That is difficult to show with a toy system. It only shows in larger systems where you really can't / don't want to say in any give subsystem module how long a certain peice of data lives. So none of those can be burdened with deallocating it. >> The problem with Controlled, BTW, is that it seems to interact with >> the rest of the language in such a way that GNAT didn't get it right >> even after ~10 years of development. Perhaps difficult w/o a formal >> semantics. > You see. Yes, I see. But GNAT is also a political problem (see the role of AdaCore, formerly ACT), so (public) GNAT not getting things right might well not indicate a problem with reading the Ada standard, but in the release politics for public version. My hint: There is no incentive to release a high quality public version GNAT. >>> On the other hand, most languages with GC get it wrong by relying >>> *only* on GC, everywhere, whereas it is useful (if at all) only for >>> memory. > >> Now, now. Having GC doesn't preclude you from managing ressources >> unrelated to memory in a manual fashion. > > Of course. No, thank you. I prefer a language which enables me to use > the same logic for all resources, so I *don't have to* manage > *anything* manually. Which as you said yourself, is difficult to do. And memory is ressource used most frequently, whereas the temptation to e.g. drop file descriptors is much less. > In other words, it's very nice that GC doesn't preclude me from doing > some stuff manually, but that's not enough. I'm appalled: You don't want GC, but no, it doesn't do enough for you? Of yourse YMMV. but when I have it, it works really well for me. >> Apart from that languages >> with GC often provide nice tricks to tie external ressources to their >> memory proxy and ditch them when the memory proxy is unreachable > > These "nice tricks" are not so nice. Most of all, they provide no > guarantee whatsoever, even that they will be invoked at all. That's not quite true. Those tricks are building blocks to implement ressources that are automatically finalized when becoming unreachable. But it's up to the library author to write a complete implementation. > A friend of mine spent long evenings recently hunting for database > connection leaks in a big Java application. That's telling something. Well -- so he was naive and should have handled / understood that part of the system better. A friend of mine spent half a month with finding problems with manual allocation/deallocation and sneaking heap corruption. Does that prove anything? I don't think so. >> And BTW - in >> fcuntional langauges you can do more against ressource leaks, sicne >> you can "wrap" functions: >> (with_file "output" (with_file "out_put" copy_data)) >> It's not always done, but a useful micro pattern. > Yes, it basically emulates something that is just natural in those > languages that provide scope-based lifetime out of the box. This is no emulation, but how FP does "scope based". Without the necessity to add exception handling at the client side or without having to introduce tagged types / classes. Isn't THAT nice? :-) > >>> Languages like Ada or C++ provide more general solution, which is >>> conceptually not related to any kind of resource and can be >>> therefore applied to every one. >> Since you're solving a problem here, which I deny that it exists > You might wish to tell this to my friend - the one hunting database > connection leaks. :-) Yes, I'll hold that up. Your friend got bitten by believing in a mechanism where he shouldn't while I deny the the necessity to manage other ressources by GC for the general case. It's a nice trick sometimes, but one doesn't need it. >> But I notice, that >> "Languages like C provide a more general solution (with regard to >> accessing memory), which is conceptually not related to any kind of >> fixed type system and can therefore implement any type and data model" >> would become a valid argument if I agreed with you. > > Except that it's not the point I'm making. No, but the structure of the argument is basically the same. The analogy should help to show why it is (IMHO) invalid. > >> In an FP I write (usually) something like: >> with_lock "/var/foo/some.lck" (fun () -> do_something1 (); >> do_something2 param; ...). >> The fact that Ada and C++ don't have curried functions and cannot >> construct unnamed functions or procedures is really limiting in this >> case and probably causal to your misconception that it would be >> necessary to add tons of exceaption handling at the client side. > Tons of exception handling (and not only - every way to leave a scope > needs to be guarded, not only by exception) are necessary in those > languages that rely on GC without providing the above possibility at > the same time. No. I've done the same in Ada w/o controlled objects, but using a generic procedure. procedure mark_data_records is new process_cache_with_lock( Operation => mark_record, ... ); begin mark_data_records(...); end; The client side has no burden with exceaption handling. > The other possibility is to rely on scoped lifetime in > the first place, where neither GC nor the above tricks are necessary > to achieve proper cleanup. Always assumed that works as a general apporach. Personally I cherish the additional freedom I get from GC. >> And BTW: In Ada I would encapsulate the ressource in a Controlled >> object (a ressource proxy or handle) and get the same effect (tying it >> to a scope). > > Yes. > >> Indeed I have already done so, to make a program which >> uses quite a number of locks, to remove locks when it terminated or >> crashes. Works nicely. > > Of course. That's my point. > (except, maybe, the crashing part, when likely there is nobody to > handle the cleanup) By "crashes" I mean uncaught exceptions propagating back to the main procedure. In those cases Finalize() runs. I've BTW, done the same on OCaml (library for automatically deallocating locks), so I don't see how GC prevents me from doing so. >>> Note also that I didn't say that references/pointers should be >>> dropped. I say that you don't need them everywhere. That's a >>> difference. >> OK, so you need them _almost_ everywhere :-). I take your point. > No, you don't. I agree for references/pointers in polymorphic > collections. That's not even close to "almost everywhere" for me, but > your application domain may differ. Yes. it does, abviously. You might not be aware, but code destined for mere consumers (as opposed to embedded code and code destined as tools for other developers) has a large amount of GUI code in it. >> 'Controlled' buys you a lot in Ada, but there are 2 problems >> (a) AFAIS (that is still my hypothesis, binding storage to scope is >> not alway possible (esp. when doing GUIs and MVC and this >> like). I cannot prove but from what I experienced I rather >> convinced of it. > > I don't follow this. > >> (b) AFAIR there are restrictions on _where_ I can define controlled >> types. AFAIR that was a PITA. > > That's a mess. I'm sorry to repeat that. Yes. But does C++ do it better? The Ada restrictions AFAIK come from the necessity of separate linking and compilation (you must be able to relink w/o looking at the body) and C++ treats that against the ability to add finalizers everyhwere. >> But how does a program become less structured by removing the >> manual memory management? The GC is not magically transforming the >> program into spaghetti code ... > You get spathetti once you start adding finalizers - the spaghetti is > then formed in both time (when something is invoked) and space (where > the code is). No. Neither GC nore finalizers make code incomprehensible. I can only assert it again, since are not discussing proofs here ore specific examples. Regards -- Markus