It says something about ProgrammingVsDesigning that while all programmers know at least one language, only a handful are ever capable of expressing what's good or bad in a language in a coherent fashion. Like all users everywhere, programmers use languages and are utterly incapable of designing one.
Programmers never even refer to the design of a language except in throwaway references like "good languages are designed by an individual with a vision while bad ones are created by committee", or handwaving like BondageAndDisciplineLanguage.
Some programmers have actually said that C++ is "better" because you can use a mix of "styles" and "choose" which paradigm you're going to use in different parts of your software. What this means is that C++ is badly designed since it contains the concepts of multiple different paradigms, and that anyone working in it will use it to produce badly-designed applications that are written using incoherent sets of concepts.
C++ can't even be said to be badly designed since it never has been. It's an evolved language, the product of random mutation of features and popular selection pressure. Which explains why its "design" is utter crap.
Why choose to use well-designed languages? For the same reason that users everywhere choose to use well-designed products, assuming they have a free choice and haven't already developed StockholmSyndrome? to a badly designed version.
What makes a good language design is not just minimizing the total number of concepts that occur in the language, nor even the unnatural concepts. A good language design is one that minimizes the total number of concepts in the language-user system. And that's important because assembler, on its own, has relatively few concepts.
For instance, goto is a simpler concept than the numerous concepts that replace it in a high level language (function call, return, hard return, exception). However, a programmer writing in assembly has to write more, in a much more disciplined manner, and has to develop higher-level concepts of the appropriate use of goto anyways.
A good language design is one that internally has the smallest number of concepts and externally supports the highest level concepts the programmer could use when writing in that language. Assembler can be well-designed so long as nobody expects programmers to use it for anything beyond simple functions. There is no usage pattern that makes C++ a well-designed language.
The number of concepts in Smalltalk is very small, and the few things that weren't built on those base concepts are broken or simply absent. The good thing is that the base concepts cover a large area, excluding notably namespaces / packages, security and HCI (MVC is crap). A direct consequence of this is that the number of vicious features in the base Smalltalk is small enough to be counted on one's fingers. Those which users will actually encounter can be counted with one hand.
How and why is a multiple-paradigm language inherently "worse" than a single-paradigm language? Although there might be a correlation, I must say that well-designed applications can be made in poorly-designed languages (and vice versa, of course). Isn't it up to the developers to make coherent use of language features?
And why is it that so many "pure" single-paradigm languages (like, all the functional languages) end up with a reputation as ToyLanguage? Of course, you bunch won't see these languages as ToyLanguage, but I'm talking about the "unenlightened" masses who know that "games are made in C++ because it's the fastest language".
Albeit questions more of MarketingOfLanguages? than LanguageDesign, I'd like you not to just rant on "impure" designs, but to prove why purity is a criterion and/or point out the specific faults with such designs. I'd also like to point to OccamsRazor (interpreted as a warning of oversimplification) - when is it warranted to start sacrificing purity for usable features? (as CeePlusPluss incremental evolution seems to have done from the start)
Oh my, it's a rant. -- SimonBrenner
In what follows the original author, probably RK, has got confused about some of those who are "discussing" this with him. To help clarify I've appended my initials to every line that is mine. Sorry for the clutter, no doubt this will be tidied sometime.
How and why is a multiple-paradigm language inherently "worse" than a single-paradigm language?
How and why is a screwhammer worse than a screwdriver and a hammer? If you don't understand such a fundamental axiom of design, you'll never be able to understand it. Yes, I COULD explain the blatantly obvious, but that would be a waste of time because you still wouldn't believe it.
- A screwhammer is superior to a screwdriver and a hammer when you are hammering something and you need to stop and unscrew something before going back to hammering. You don't have to go digging through the toolbox to find the screwdriver. Instead, you flip your screwhammer over and remove the screw, flip the screwhammer back and finish hammering. It also helps avoid the GoldenHammer anti-pattern because you'll be less likely to attempt removing the screw by hitting it with the hammer rather than trying to remember where you left your screwdriver. -- ???
- Furthermore, careful combinations of tools are common and accepted as better than a collection of separate tools. Witness typical pliers, which often include wire-cutters, claw-hammers which include nail removers, and crimpers, which include wire-strippers.
Isn't it up to the developers to make coherent use of language features?
Obviously not. There's no such thing as "coherent" features anyways. There's coherent designs and features which belong to solely one coherent design versus others that belong to another incompatible but internally coherent design. For programmers to be able to know which features are "coherent" with each other, they would have to have an appreciation for design. And we already know from the existence of C++ that they do not.
And why is it that so many "pure" single-paradigm languages (like, all the functional languages) end up with a reputation as ToyLanguage?
I honestly couldn't care less. My job isn't to explain the mistakes of the past, it's to kick ass and roll heads.
Albeit questions more of MarketingOfLanguages? than LanguageDesign, I'd like you not to just rant on "impure" designs, but to prove why purity is a criterion and/or point out the specific faults with such designs.
If you're really serious about it then well-designed anything are:
- easier to learn
- easier to understand
- easier to use
- easier to maintain
- easier to extend
What that means is that a well-designed language will be more quickly learned, more comprehensively understood, will cause fewer programmer errors, will
have fewer language errors and will be easier to extend in future.
- He asked why "purity" in a design is important and you responded with tautologies about "well-designed" things. You've missed the point: why does conceptual purity equate to good design?
- YOU missed the point. "Good design == conceptual purity" is the tautology, everything else is implications deriving from conceptual purity.
- Hmm. This appears to be an assertion without evidence. I don't understand why good design is synonymous with conceptual purity, or, more particulary, with using a single paradigm. I don't see why a well-designed language can't have objects, functions, and databases combined. Some things are more naturally thought of as objects that react to messages, other things take an input and produce an output. Why can't a well-designed language be a harmonious combination?
- Because there is no such beast.
- To an engineer, "good design == process or model which results in visible advantages" so saying that good design results in blah blah blah is just a tautology.
- To a designer, "good design == conceptual purity" by definition. The real assertion without evidence is stating that the advantages of good design are blah blah blah.
- Guess what? I'm a designer, not an engineer.
- A good design is one that has the smallest set of concepts that provides a complete cover for the system. This is the same as an elegant theory in physics. A single paradigm provides a complete cover. A language that supports multiple paradigms by definition has more concepts than a complete cover.
- Empirically, the reason why a minimal set of concepts is needed is so as to remove choice. Choice is a bad thing and so must be justified. Choice very rarely is justified. In the case of C++, the choices of concepts at every code location is simply not justified.
- You get 90% of the benefit of multiple paradigms simply by choosing a paradigm for a software project. You get 90% of the leftover benefit by interfacing between languages from different paradigms. The leftover 1% benefit is not worth the cost of multiplying the conceptual overhead for ALL software development by a factor of 2 or 3 (for a "harmonious combination" which C++ is not).
- I agree with much of what you are saying. Specifically, I agree that removing choice is often a good thing. Having one, natural and obviously "right" way of doing something makes code easier to write, easier to read, and easier to maintain.
- Hoever, there are some points that still seem to be assertions without evidence, and which appear to me to be wrong. Specifically, if I have one thing that is most naturally a function, and another that is mostly naturally an object, how is having a single paradigm language going to be the right thing to use?
- "A single paradigm provides a complete cover." Assembly language provides complete cover for implementation, but not for programmer design. When I write programs I find that some parts are most easily expressed in the functional style because they are boxes that take input and produce output. Other parts are most naturally expressed in object style because they are independent "things" that react to messages and send messages. Other parts are imperative, and others as unification systems. To write my code in a single paradigm would result in my code being harder to learn, harder to understand, harder to use, harder to maintain and harder to extend. By your own definition my program would be of a worse design in every possible way, and I would be forced to it by a "well-designed" language.
- Complexity has to go somewhere. If a language allows me to express my programs clearly, simply, and without undue complexity, then that language is well-designed for my purpose.
- Guess what - I don't pontificate about designing programming languages, I use them.
- Which is why, like any typical user of anything, you can't express what makes up good design even after experiencing it. And also why, without experience of good design, you won't even be able to recognize bad design for what it is.
- Richard, you sound like an architect proclaiming the beauty and artistic integrity of a building, while all who live in it curse the thousand and one minor irritations that blight their lives.
- Given your description of the many "styles" in a single piece of software, there are two possibilities that come to mind. The first possibility is that you don't really understand Smalltalk and Lisp and you're simply incompetent. The second possibility is that you write exceedingly strange code for some exceedingly unusual domain. Without proof to the contrary, and given your trivializing talk of "styles", I'll go with option #1. And given your lack of experience with good design, your judgement of the design of C++ matters not a whit.
- Bzzzt - wrong. I won't say what I think of C++ because I don't use the sort of language you use. I suspect that our thoughts on C++ are very similar indeed. I believe that some things are better modelled as functions and some things are better modelled as objects. I further think that a language that lets me express that directly is better than a language that forces me to use one model for everything. I don't see how you can fail to understand that, but clearly your self-proclaimed, unrivalled vision doesn't see it.
- And in any case, your argument that a program that "naturally" fits multiple paradigms would be "harder to learn" if coded in a single one is just so much bullshit. The cost of constant paradigm switching without any clear indication of where paradigm boundaries are (eg, by language boundaries) more than outweighs any miniscule savings from a "natural fit" of your software. That you don't perceive this cost just proves you're out of touch with reality. As proof of it, you learned C++ without thinking it was an insurmountable cost.
- Perhaps my understanding and experience of my problem domain allows me better to judge that the programs I write are better expressed in a multi-paradigm language. Perhaps your lack of understanding and experience ensure that when you make pronouncements about my problem domain makes you sound arrogant and uninformed.
- This isn't going to go anywhere. You, as a designer, will continue to claim that your artistic understanding and breath-taking scope of understanding will allow you to make unchallenged proclamations about everyone else's problem domains. I and the programmers who work for me will continue to write programs that use objects, functions, state-machines and databases working together in a clear, elegant design.
- Finally, I agree with you far more than my comments may imply. I agree that clean, clear, conceptual purity in a language is a GoodThing(tm) and should be striven for. I simply don't agree that this requires a program only to support one paradigm. I want my language to reflect the domain I'm modelling, and my domain has functions, objects, databases and state-machines. Yes, I can model each in any, but why should I? Writing correct, maintainable programs in this domain is hard enough.
I'd also like to point to OccamsRazor (interpreted as a warning of oversimplification) - when is it warranted to start sacrificing purity for usable features?
The entire set of magic features (deviations from a pure design) must be small enough to be comprehensively explained in a single hour. If you've gone past this limit, then it's time for a redesign.
I'd like to point to quote by Albert Einstein -- "Make everything as simple as possible, but not simpler.".
How do you know that single paradigm language is NOT too simple (simpler)?
If having purely functional language means user must go through hoop to describe object or state change then may be it's too simple, isn't it?
Having single paradigm may be too simple, may be a good language shoud have two or may be three paradigm and that would be considered simple language. -- AnonymousDonor
How does this train of thought apply to human languages?
With one or two exceptions, they're all evolved languages, so it doesn't apply.
EditHint Meta discussion: do we need a category for "language design"? We have a syntax category, but language design is about more than just syntax.
See also FormFollowsFunction, LanguagesFromDesignersPerspective, NonOrthogonalLanguageFeatures
JuneZeroFive