Andrew Lentvorski wrote:
Christopher Smith wrote:
Andrew Lentvorski wrote:
Christopher Smith wrote:
There are quite a few languages that do everything C++ can do, and
they do it much better.
All evidence to the contrary aside....
What evidence to the contrary? Popularity? That's about all I can
think of.
Popularity and success. Those are difficult things for languages to
achieve, and one is foolish to dismiss them out of hand or fail to
appreciate the reasons as to why.
I don't dismiss them out of hand. C++ had a very large backward
compatibility advantage. The question is whether C++ owes its
position to being good or being first.
C++ wasn't first... by a long shot. It's just the first that survived
advent of C++. ;-)
The trend suggests that it is because it was first:
http://www.tiobe.com/tpci.htm
While I have a few quibbles with the overall methodology of those
rankings, it's probably as good as any other.
The fact that Java and C are holding their places while C++ is losing
its place speaks volumes.
I guess it depends on how you fudge your data. I see all three have lost
~5% in the ranking since the start of the tracking, with C taking the
worst beating. C++ started off lower, so I guess that means it lost more
relative to its base, but "holding their places" is highly misleading.
They are all declining as the emphasis shifts more away from system
languages. Java actually had a horrid collapse there ~2005, so arguably
its base may actually be the one that is most volatile.
Either way, you'd *hope* to hell that as new languages matured that
older languages would lose some prominence. I'd hate to think that all
these new languages weren't providing some advantages over C++ in at
least *some* manner. I would still argue that any language that is up in
the top 10 is obviously serving some useful function.
- Design patterns originated in the Smalltalk/OOPSLA community
(indeed, the very same folks as were involved in Agile methods and
such), not the C++ community. Perhaps this is evidence of
deficiencies in Smalltalk and object-oriented proramming in general,
but nonetheless, this is where it was developed and where it caught on.
Among the minority. And it escaped into the programming community at
large with C++ and the STL.
Wha? Now you're just rambling crazily. The Stepanov's work was
independent of, and largely orthogonal to, the design patterns stuff
(not to mention that it predates it for the most part). Just 'cause they
both have the concept of "iterators" (which was hardly original at the
time... which is part of what makes them a Design Pattern...) in them
doesn't make them connected. In general, Stepanov's work was all about
algorithms and data structures, while the Design Pattern stuff is
(surprisingly ;-) about design.
And, in fact, several of the patterns simply *do not apply* to
Smalltalk--they *only* apply to C++ or similar statically compiled,
non-introspective, manual memory managed languages.
Of course, by making that statement you are indicating that you
mistakenly attribute GoF as somehow being the whole of DP (and in so
doing pretty much missing the whole point). Let's go with that though.
When the GoF book came out, I was working in the Smalltalk community,
and the reaction there was that not only were most of the GoF patterns
well established in the Smalltalk world, but almost all of them were
embodied in parts of the standard Smalltalk class library. So, I'd be
intrigued to hear about which one of these patterns only applies to "C++
or similar statically compiled, non-introspective, manual memory managed
languages" (I'm hoping you meant statically bound and/or statically
typed, as "statically compiled" is a meaningless language trait).
Interestingly, my experience has been that many of the design patterns
cataloged in the book are actually more beneficial and easier to
implement in a dynamically typed, introspective language with automatic
memory management. ;-)
- The notion that one language is superior to another simply because
one can implement a design using native language keywords and
operators while the other must use a library is..... the kind of
thinking that leads to hideously complex syntaxes like... C++.
At no point did I talk about syntax or keywords.
I still maintain my point about design patterns being deficiencies of
the languages--that *includes* Smalltalk.
Many of the "object oriented" related patterns are about how to deal
with the deficiency of "single-dispatch" ie. all object functions have
an implicit first parameter of self/this/etc. This *does not exist*
in a language with proper multiple dispatch. (Note: Java also has
this deficiency)
If you don't think multiple dispatch is about syntax (or that you can't
add it to languages like Smalltalk if you really want it)....
Yes, so it is safe to say that this is a deficiency found in almost all
the top 10 languages in the afore mentioned site. Just how unpopular
does a feature have to be before not having it tightly integrated in to
your language is no longer viewed as a deficiency? ;-) Are we going to
start talking about how all of OOP is deficient because it really is
just a poor attempt to address languages that have state or that design
patterns with threads and locks are just a failure to address
concurrency properly in the language?
While traditional, single-dispatch OOP might seem like such a flawed,
and deficient practice to you that it ought to be ridiculed and never
taught, it has been so popular largely because it is so accessible, and
it is easier for people to think up case-by-case design strategies for
implementing multiple dispatch where needed, rather than work with it
all the time.
Many of the "behavioral" patterns deal with the fact that the
languages do not have a clean delineation between counting, doing
something to each element of a collection, or unfolding tail
recursion. This is a deficiency of the language.
Yeah... Smalltalk definitely distinguishes between all three. I'd argue
C++ does, but of course you'd insist that all the facilities that C++
has for distinguishing these things aren't readable (somehow "foo = map
(predicate, collection)" is sooo much more readable than
"transform(collection.begin(), collection.end(), foo.begin(),
predicate)"... I'll never grok why).
- One could write an entire book of design patterns for purely
functional languages (indeed, there are more than enough essays/white
papers on Haskell to assemble one right now), declarative languages,
scripting languages (Rails anyone? ;-), or whatever else is your
favourite pet programming language/style.
Yet nobody has. Or, if they do, they call it a "Cookbook" rather than
trying to foist it off as a great contribution to CS. Why?
Well, for starters, a lot of the existing design pattern works already
cover that ground (reading the first few PLoP books gives you most of
the design elements of Rails), so if they wrote a book as presenting new
design patterns, people might accuse them of regurgitation. In the case
of functional programming, it has traditionally been the domain of more
academic types who already have their preferred manner of codifying
design practices (indeed, design patterns was seen by many as a reaction
by lay programmers to years of dealing with academic papers suggesting
how to write software). Particularly when it comes to purely functional
languages, I find it's hard to get *anywhere* without having first
learned a bunch of established design practices, and beyond that base
set, nobody (or at least next to nobody) has really established yet a
canonical set of design practices for functional programming that are
helpful in the real world. Combine all that with the relatively limited
audience and it doesn't take much imagination to see why such books
aren't getting published.
Because these other languages are not as deeply deficient. For
example, I don't have to *think* about an Iterator to walk over every
element in a container in Python/Ruby/etc.
...and yet both Python and Ruby have sections on iterators in the
language references and tutorials.
If I have multiple dispatch, which I can do if I can introspect, I
don't have to build deep hierarchies of responsibility. etc.
a) AFAIK, none of the design patterns I've seen suggest building deep
hierarchies (particularly for the C++ implementations).
b) Implementing multiple dispatch through introspection *without*
employing one of the behavioral design patterns from GoF is... interesting.
Looking back at the table of contents in my copy of Design Patterns I
am *amazed* at how little it applies to just about any language that
anyone considers a useful successor to C++ or Java.
Okay, Ruby is one of these "successor" languages. Not only does Rails
employ design patterns, it *specifically cites and names classes* based
on established design patterns (like ActiveRecord, Commands, MVC,
adapter, abstract factory, ....).
Unfortunately, constructors and destructors are excruciatingly
difficult to get right in the presence of exceptions. The fact that
that you have to pull out about 3 different books to get this right
says that something is broken.
Or perhaps that there is something that can be learned.... ;-)
Yes. Exceptions and manual memory management don't mix.
Sigh... gargling at the fountain of knowledge....
--Chris
--
[email protected]
http://www.kernel-panic.org/cgi-bin/mailman/listinfo/kplug-lpsg