Re: Alternatives to C: ObjectPascal, Eiffel, Ada or Modula-3?



Stephen Horne wrote:
On Wed, 29 Jul 2009 07:38:53 -0400, Oxide Scrubber
<jharriman@xxxxxxxxx> wrote:

My problem with it is the lack of a garbage collection. That is just not
acceptable to me these days. If you manually allocate memory, then you
pretty much have memory bugs, it's as simple as that.
That is simply not true. If you don't know how to do resource management
properly, you're not ready to write commercial code in any environment.
What utter balderdash. You make GC sound like training wheels, when in fact it is very useful even for major production-code systems.

Or maybe there's a middle ground, where it really doesn't matter much
whether you use GC or not for around 99% of high level code.

If you don't mind 10+% code bloat micromanaging deallocation.

The point being that in GC languages, memory cleanup is automated, but
other resource cleanups aren't. You end up having to do manual
cleanups anyway, if only for those other resources.

What's better, having to do manual cleanups for 100% of your resources or for only 1%?

Not to mention, those few resources tend to have clear "ownership". Window handles are associated with windows; you release them when you get the window-closed event. File handles and most other non-GC-able resources are typically associated with open I/O streams. Network sockets are often dealt with using an event-driven framework. File I/O tends to be done in the scope of a single function or method call.

So all of the non-GC-able resources tend to be ones with distinct "owning" procedures or UI components, and an easily delineated lifespan. Conversely, nearly all the resources it's hard to decide when to explicitly delete are just memory, and GC works very well in that case.

Trouble is, where C++ allows you to bung that cleanup in a destructor
and trust that it will be called at the appropriate time, GC languages
don't support this. You need explicit non-destructor cleanup methods
instead, and of course, the user has to remember to call them *every*
time for that class, not just in an occasional special case - even
though the normal pattern for the language is
no-explicit-cleanup-needed.

This is a slight problem in languages like Java that have GC but no flow-control abstraction. There coders resort to idioms involving try/finally or similar constructs to clean up streams and the like after use.

Languages like Lisp and Smalltalk are another story: it's easy to have a with-open flow control construct that runs some subordinate code and then cleans up, and to have this be the standard way to use such things. Common Lisp has a macro named with-open that does exactly this.

It simply is not a problem in languages with good macros or proper closures. (Lisps tend to have both!)

In short, both GC and non-GC languages sometimes require special
measures to ensure proper cleanup.

GC languages occasionally do. Non-GC languages always do. I guess "occasionally" and "always" do average to "sometimes". :)

Both have situations where cleanups are easily missed, leading to bugs.

But the frequencies and effects are different.
C++: memory leaks or freeing still-used structures; frequent; crashes app.
Java, Lisp, etc.: file handle leaks; infrequent; results in a file not being deletable or similar until the program is quit, and in a long-running server, eventually a crash.

One of these two is responsible for very common crashes of desktop applications, causing untold damage every year through lost productivity. The other is responsible for the odd glitchy behavior and the occasional two-minute downtime of a server when some process dies and is automatically restarted.

It's pretty clear which is worse.

But neither GC nor non-GC is a magic cure for all ills.

Nobody claimed that GC was a magic cure for anything. But it beats the heck out of non-GC all the same.

"Neither is a magic bullet, therefore neither is better than the other" is ridiculous reasoning.

I compared notes with a Java programmer about 5 or 6 years ago and was
surprised to find he'd had more problems with memory leaks and missing
cleanups than I had.

Ah, here comes the inevitable anecdotal evidence. How much of a Java n00b was this "programmer"?

IIRC, the memory leaks related to forgotten
reference somewhere indirectly keeping masses of dead objects in
memory due

Sounds like packratting. A n00b mistake, generally committed when someone is both unfamiliar as yet with java.util.WeakHashMap and still in love with global variables.

As for missing cleanups, he certainly mentioned trying to re-open files
that were still locked, and there was a whole bunch of stuff about network
sockets.

More n00b mistakes. N00bs will always manage to shoot themselves in the foot from time to time. It does not reflect upon the language, or GC, or whatnot.

Consider memory management of an object that is shared and passed around at need among many related parts of a program. Keeping track of when it's no longer in use rapidly becomes nontrivial as the complexity of the code using it goes up. Eventually, you'll be reference counting or doing something else like that, and before long, you'll end up with an ad-hoc, informally specified, slow, bug-ridden implementation of half of a garbage collector.

This is a good reason to have a good set of smart pointer templates in
the standard library.

A wonky and piecemeal solution, when GC will take care of all such cases, uniformly, and leave you only to worry about those handful of objects that hold onto OS resources like file descriptors.

And one day, GC will be an OS feature and even that issue will go away.

Come to think of it, isn't CLOS a slow and confusing implementation of
half of C++, or Java, or Smalltalk or whatever?

I wouldn't know; I tend to write Lisp in a functional style when I write Lisp, and therefore don't use CLOS.

Using a bit of reference counting on occasion (when it's needed - 99%
of the time it isn't) is *very* far from "ought to be using GC".

Reference counting ends up eating quite a few cycles for every short-lived object. GC tends to eat up cycles only for long lived objects, and in most systems the vast majority of objects are short-lived.

Switching to Common Lisp as a kneejerk reaction to avoid having to use
one or two reference-counted types in a system where thousands of
types need no "GC" at all would be stupid.

Did I say anything about switching to Common Lisp? There are other Lisps, Java, and Smalltalk if you want garbage collected languages. (Java lacks decent closures, though, and only the Lisps have decent macros.)
.



Relevant Pages

  • Re: LISPPA
    ... > memory resources. ... do in Common Lisp with code that runs about as fast. ... >> comparing Lisp with languages like C, Pascal and Basic, ... If by "visual programming" you mean the sort of ...
    (comp.lang.lisp)
  • Re: Newbie question about "cons"?
    ... I think this is relevant to the history of Lisp. ... mega-large databases of facts that can't all be "in memory" at once. ... ultimately know that there are locality issues no matter what you do. ... In fact, the choice of lists vs arrays in languages, something near ...
    (comp.lang.lisp)
  • Re: LISPPA
    ... >> memory resources. ... > do in Common Lisp with code that runs about as fast. ... in "weaks languages": iteration instead of recursion and "local" ... I'm programming in Pascal since 1990 year, ...
    (comp.lang.lisp)
  • Re: Executables: Why all the abuse?
    ... CPU resources are infinite is one of the causes of bloatware (but ... Total memory ... But these are all about Lisp compiler/runtime implementations ...
    (comp.lang.lisp)
  • Re: a potential lisp convert, and interpreting the shootout
    ... computer systems, not languages. ... there is something very wrong with the lisp benchmark which is about ... it is impossible to compite to C in memory ...
    (comp.lang.lisp)