Programming Languages Shape Thoughts

This is a part of a broader theory called LinguisticDeterminism. Some have wondered if this is true of ProgrammingLanguages.

Some off-the-cuff examples of potentially bad influences from specific programming languages:

Maybe you've seen something like this happen in your experience, even if you believe the specific examples above are rubbish.

Some interesting questions to ask are are:

Why does this happen? (assuming it does)

Is this a cause or an effect?

What can be done to counter the bad symptoms?

Does it suffice to create a project-wide attitude that, for example, treasures the XpSimplicityRules?

Does switching languages help? Maybe it's just enough for the programmers to learn other languages?

In the PsychologyOfEverydayThings, Donald Norman talks of affordances. On a door, plates afford pushing, and handles afford pulling, so even if you have the most obvious Push or Pull sign, people will still try to do the wrong thing if the door affords it. Likewise, if a programming language makes it easier to do the wrong thing than the right thing, then the wrong thing shall be done more often. --NickBensema

Here's an example. Consider the W3C Dom api (XmlDom?) for working with XML documents. The Element interface has a method getElementsByTagName() which returns "all descendant Elements with a given tag name". It does NOT have a method for returning "all child Elements with a given tag name", and looping through all child nodes and picking out just those which are elements and which have the right name is a bit of a pain. So when people want "the child element named 'Foo'" (knowing that there's just one), they tend to use getElementsByTagName().item(0). That is MUCH less efficient (it has to search an entire hierarchy) and it can even give the wrong result if an earlier child has some decendent named 'Foo'. If there were a getChildElementByTagName() method, no one would get it wrong.

But hang on a sec -- you're talking about an API, not a programming language. [but see ApiIsLanguage, FrameworkIsLanguage] And, your example points out that lazy folks might use this facility incorrectly by assuming that a certain condition exists ("knowing that there's just one") without actually checking that the condition is met. This is bad practise that might be held in any language. Do you maybe have a better example? [I believe the point of the above is that the API doesn't have an affordance _showing_ what the right thing is. Calling someone lazy for acting on an assumption doesn't add the affordance, nor change the influence that lack of affordance has on creating certain assumptions in the first place.]

OK, how about this one (from CategoryPitfall):
  if( enemy_missiles_detected = true ){
This error seems to happen far more often in C-like languages than in other languages -- I believe that's because it's so much easier to make this error.

See for some more thoughts on affordances in general.

I would say that the run-time library supplied with the language causes at least as much influence as the language itself. It has been mentioned, for example, that MicrosoftFoundationClasses teaches people bad OOP techniques, because it is supplied with source code and people read the code and think that this is how things should be done. On the other hand, the DelphiLanguage run-time library (VCL) is quite well designed, and it is seen in many good DelphiLanguage programs that their style is similar to VCL.

I don't use Perl, so I don't really know what kind of run-time library does it have... -- DmitryJemerov
IMHO, I think that the developers education may have the greater influence on how they make use of a language. I've known developers who don't like writing OO code completely ignore a languages OO capabilities, simply because they have learnt most of their design and programming techniques in a procedural language. I suppose that the features of a language do restrict and therefore shape how we design/build software, but our own education can impose boundaries not present in the programming language, or overcome ones that are.

-- TobinHarris (waffling a little!)
ArrayOrientedLanguages (AplLanguage, JayLanguage, KayLanguage) benefit from the programmer's ability to view a problem in the context of arrays and vectors. It can be hard for those with a conventional scalar procedural language background to understand how to leave his For, While, and Do looping constructs behind.
Read the paragraphs about the reported influence of word order on thoughts in SapirWhorfHypothesis. ForthLanguage users and other prefix language users might possibly have different tendency in their thinking. In addition to that, traditional procedural languages demand you make every sentence in verb-object imperative form, whereas in a OOP language, you must think in subject-verb-object descriptive form, in which case NOUN is the central concept while VERB is the central concept in procedural languages. --JuneKim
I'm sure this effect exists, but not in the way the author of the following thought it did:

The LispLanguage has funny little names that mean nothing to the uninitiated ("cons", "sexp", "car", "cdr"). Does this encourage more of the same from developer-written code?

The answer to this is a resounding no. However, the LispLanguage most certainly does shape your thoughts, by freeing you to express them in constructs which are on equal par with those of the language. Similarly, C++ forces you to think along the grain of the language (hence, books like the GangOfFour book, which show you how to express common concepts in C++). More than 1/2 of those patterns don't exist in the LispLanguage, simply because they can be naturally expressed in the language without extra design constructs. So--- ProgrammingLanguagesShapeThoughts but not at the trivial level of syntax. --AlainPicard

OK-- I want to dispel a common misconception and slam against the GangOfFour here. The GangOfFour book does not only tell you "how to express common concepts in C++". That either comes from a very cursory reading of the GangOfFour, or an ignorance of C++. See the DesignPatternsSmalltalkCompanion to find a version of the patterns completely without any reference to the C++. The patterns will always win through. -- KyleBrown

Hum. I guess I take offense. :-) I'm sorry to be sounding harsh, but I've read the PatternsBook? very closely, and thought it was a godsend. I think I know C++, at least well enough to have delivered a real-time telco app in it. and I maintain my statement above. Please don't take it as a slam -- I think the authors did a wonderful job, but that job was (mostly) only necessary because C++ is so crippled. Of course, that's just one man's opinion... --AlainPicard (also check out DesignPatternsInDynamicProgramming for a perspective written by an expert in CommonLisp).

     I DO NOT

The best way to see the degree to which this is true is to do something like (a) write the same program in two languages and see how different the two results are, or (b) translate a program from one language to another. No fair picking highly similar languages like C++, C#, and Java (unless you are pounding extra-hard on their differences). Pick some languages that are really far apart, like C++ and Lisp.

I know about a dozen languages, and I can think of dozens of examples where a few lines of code in language one works out to pages and pages in language two. This doesn't always mean that language two is a lower-level language: many times I can find a complimentary example in language two which is a few lines long but works out to a few pages of code in language one.

A language influences you because you think "Ah, I can write that in a few lines of code." And that affects everything you try to design. If you are used to Scheme then you are used to being able to pass functions as parameters to other functions and receive new functions as results. You are also used to tail-calls and the possibility for ContinuationPassingStyle. So when it is possible to solve a problem that way, and when you are used to Scheme, you look at the problem and your brain goes, "Aha! Pass functions as parameters and..." and you realize you can't do that in C++, at least not with the same ease.

Not all thoughts are shaped by the programming language, but one of the big ones that is is your evaluation of what is easy and what is hard.
The idea that ProgrammingLanguagesShapeThoughts is central to the BlubParadox -- StephenHutchinson
The PerlLanguage has a very terse and (initially) cryptic syntax. Does this influence developers to write more cryptic code? Furthermore, it has a somewhat clumsy class-definition syntax. Does this add to a FearOfAddingClasses?

It absolutely does, at least in my case when I am writing in PerlLanguage, although, I guess it's not so much fear as dread. I don't seem to have this problem in RubyLanguage.
I have noticed that the more I use higher-level languages (e.g. Perl, Lisp, or Ruby), the more I am willing to do "difficult" things in C. I think it's because while using the higher-level languages, I learn a new technique or concept without worrying about details like memory management. Then, when I need a similar thing in a C program, I just have to add all the little details that C forces you to worry about.
Somebody said about PythonLanguage that it is possible to write in that language with the speed of thinking. So, probably programmers of such a language are free from being shaped by the language? The problem arises when they are faced with "slower" syntaxes and need to explain their thoughts harder -- RomanSuzi?

I don't think so...because I find it's possible to write in any language I'm reasonably familiar with at the speed of thinking. The trick is to avoid FightingTheLanguage?; if you're comfortable with the idioms and paradigms of the language, then you don't need to "translate" into computer code. It doesn't matter whether that code is in Java, PHP, C++, Python, Scheme, or Haskell. There've been times when I've started typing (in Java) as my boss was explaining the problem, and had a working program by the time he got up to leave the room.

The advantage of higher level languages is that they structure your thoughts in a manner that's more conducive to solving the problem. Sure, I can write C as fast as I think, but I have to think about memory management and parameter passing and side effects and everything else. If I'm writing in Scheme or Haskell, however, I can usually describe the problem in terms of the problem domain and not worry about the nitty-gritty implementation details. -- JonathanTang

The biggest difference is the scope of a language. If you can use arrays, you almost automatically will use them. But as useful as they are in certain contexts, they aren't really necessary most of the time. For my page on verb conjugation written in HTML (HyperTextMarkupLanguage) + JavaScript, I did use for the universality of simple variables stam1, stam2 instead of stam[1], stam[2], ... because I believe that earlier version of JavaScript interpreters won't run arrays. [see ] Only for the display on screen I did afterwards complain about my choice. An other thing is the absence of a READ / DATA structure, so I had to test everything by a new IF-construction. -- PieterJansegers

Nearly every C program I've ever seen has the main() function either at the very beginning, or at the very end. -- DavidCary

See: EverythingIsa

View edit of March 26, 2009 or FindPage with title or text search