Looking at the syntax of the programming language C and others inspired by it, I cannot help but ask the question in the title. Mathematics, logic and other subjects have been existing for many ages and so have natural languages and all of their symbols. Still, instead of respecting these conventions fully, designers of languages such as C have gone against them, for example by using the very old &, used in logic and natural language to denote conjunction, for something totally different, or by using the well-known = and == in unexpected ways, or by using ! for negation. Why?

Even if there were constraints to work with, certainly a programming language designer and implementor could make the syntax much more readable, less cryptic, and still concise and more natural, respecting established conventions? After all, there have been examples of that (Wirthian programming languages). And they can certainly do it these days.

Furthermore, certainly subjects such as philosophy, logic, mathematics and natural languages are very much primary and very essential subjects without which there would not even exist any computer science and no programming language. The symbols there used are very much known by many or they are at least standard. Why then go against established principles?

  • 1
    $\begingroup$ This sounds awfully broad. If you have a specific convention in mind and a specific aspect of C syntax, you could ask why that aspect of C syntax is the way it is and not some other way; that sounds answerable. But your current question seems too vague and broad to be answerable, as it's not clear what aspect of C syntax you are thinking of nor which mathematical convention you are thinking of. $\endgroup$ – D.W. Apr 21 '19 at 19:19
  • $\begingroup$ Of course it is answerable. (And I did mention a few C-like examples and the like.) All you have to do is read it, understand it, and answer it. I don't see how it is vague: the words and their meaning are pretty clear. Broad, if it even is, is not equal to vague, if you meant that. $\endgroup$ – user101144 Apr 21 '19 at 19:33
  • $\begingroup$ Our site is designed for narrowly scoped technical questions that can be answered in a paragraph or two; where answers can be supported by evidence or facts, not mere opinion; where we don't have to guess what you might have in mind; and where the criteria for evaluating are clear to others who want to vote on answers. I don't know if you realize this, but questions that are too broad are often closed, as they tend not to work well on our site format (see e.g., cs.stackexchange.com/help/closed-questions). I encourage you to edit your question to narrow it down as I suggested. $\endgroup$ – D.W. Apr 21 '19 at 19:38
  • 3
    $\begingroup$ Right now you're effectively asking many questions; one for each part of C syntax that differs from mathematical notation. The answer for each might be different, which is part of why this kind of question doesn't work well on our site format. To provide a complete answer, one would need a compendium of all those differences and the reasons for each one, which is too much to expect from a single answer. Worse, we have to infer what those questions are, because you haven't listed specifically which parts of C syntax you're especially interested in. $\endgroup$ – D.W. Apr 21 '19 at 19:39
  • $\begingroup$ That's a question about the design of C. $\endgroup$ – Yuval Filmus Apr 21 '19 at 23:06

Today, most people who learn a programming language know very little mathematical notation and are more familiar with other programming languages, and with symbols that are available on their computer keyboard. Of course, this wasn't the case in the 1950s and 1960s when some of the major programming language families that exist today appeared.

A lot of programming languages use a C-like syntax today because this has become the earlier convention. C established conventions such as braces {} to delimit code blocks, semicolons ; to delimit instructions, dot . to access an element of a compound structure by name, the equal sign = as the assignment operator, double-equal == as the equality operator and != as inequality, && and || as logical-and and logical-or, square brackets […] for array indices, etc. C also participated in some conventions inherited from mathematics, such as the decimal notation for numbers, infix binary operators with parentheses for precedence, and the function call syntax with parentheses around the argument lists and commas to separate arguments function(argument1, argument2, …).

The conceptors of C, like Wirth, followed some conventions already established in ALGOL. I think (but I'm not sure) that's where brackets for array access comes from.

Syntax choices are of course very strongly influenced by technical reasons: most languages use syntax that programmers will be able to type on their keyboard. To start with, most languages represent their source code as a sequence of lines, each line being itself a sequence of printable characters. This rules out some aspects of mathematical notation such as subscripts, superscripts, superposition (like the fraction notation), etc.

The set of available characters is usually limited to what typical computers of the time allow people to type easily. This self-perpetuates because operating system and keyboard manufacturers keep making these characters easily available. The basic standard set of characters today is ASCII: computer systems that don't support ASCII are extremely rare. Some of the characters in ASCII today weren't commonly available in the 1950s and 1960s, which explains why some languages that trace their roots to this time period don't use all of them.

An example of characters that are used by mathematicians, but weren't commonly available on computers at the time, is the logical operators $\wedge$, $\vee$ and $\neg$. FORTRAN and ALGOL 58 spelled them out AND, OR and NOT. C (following some of its ancestors) used &&, || and !. Mathematicians never used & for conjunction, as far as I know¹: that came from Latin (& started out as a ligature for “et”, which is how the Latin word for ”and“ is spelled). Later versions of ALGOL added ∧ and ∨ as syntax for boolean operators, but since most computers didn't have them, they allowed other spellings, including /\ and \/, which contributed to the imposition of the backslash as a standard character.

Some languages stray further from classical mathematical notations than C. A major example is Lisp, where the syntax for a function call is (function argument1 argument2 …) and there are no infix operators. Lisp made this choice in the interest of uniformity: there is only one syntax for function calls and not many ($2+3$, $2^3$, $2x$, $\sin x$ are some examples of mathematical notations for function calls that don't follow the usual $f(x,y,\ldots)$ syntax). This uniformity has some theoretical advantages (Lisp was heavily inspired from the mathematical work on the lambda calculus), technical advantages (Lisp makes it easy to manipulate code as data objects), and sociological advantages (it makes the language easier to learn: for example you don't need to learn operator precedence).

A (basically the) notable language that baked in more classical mathematical notations is APL. It's still limited by the line syntax, but uses a special character set that includes characters such as $\leftarrow$, $\rightarrow$, $\neq$, $\neg$, $\subset$, $\supset$, etc. The special character set was a strong barrier to adoption because it required special software and made it harder to learn to type programs. The syntax of APL makes it very terse, and is a reasonably good fit for numerical programming, but it isn't particularly readable.

Beyond symbol availability, another reason for programming languages to depart from mathematical notation is the need for new concepts. Most programming languages incorporate syntax for imperative programming, with major concepts that mathematics doesn't have: operations done in sequence, assignment. For sequencing, the most logical character would have been . following the typography of most languages, but that character was also used in mathematics for decimal numbers. ;, which is not used in mathematics, was the next logical candidate. For assignment, some languages tried to introduce $\leftarrow$, but since it wasn't available in typical character sets, it never really took on. The symbol = was a logical candidate for both equality testing (“are these things equal?”) and assignment (“make this equal to that”). C uses = for assignment and == for equality testing. Other languages made different choices. ALGOL used the arguably more fitting := for assignment (more fitting because it's asymmetric, leaving the symmetric symbol = free for the symmetric concept of equality). PL/1 uses = for both and distinguishes the meaning from context, but this requires the language to distinguish between contexts that allow an assignment and contexts that allow a predicate and not to have any context that allows both. Some languages go closer to mathematical notation and use syntax like set x = … or let x = …; I think the designers of B and C considered this too verbose. I think FORTRAN was the heaviest original influence on imposing = for assignment.

¹ Linear logic uses $\&$ but that's not the ordinary conjunction and that came later.

  • $\begingroup$ Thank you for the effort. I would seem that logic is a more fundamental, more essential or, so to speak, greater subject than mathematics, for it is more universal or overarching. In any case, even with keyboard restrictions, certainly programming languages could have been designed to look more in tune with established conventions and more natural? If one has a set of available symbols, then would one not want to conform and also make it as natural as possible, so as to make the best of it? The # sign, e.g., looks like inequality. $\endgroup$ – user101144 Apr 22 '19 at 11:36
  • $\begingroup$ C had already since its beginning certain symbols at its disposal. Why not indeed design the syntax different? I mentioned things such as logic, philosophy, languages, and so on. Certainly C could have retained its terseness while conforming very much to established principles? Certainly one could have, e.g., used ~ for negation in different contexts? Or & for conjunction? Or # for inequality. And to refrain from == and use = in different contexts, and to refrain from ! for negation, and so on? Is it a way to simply be cryptic for some reason? $\endgroup$ – user101144 Apr 22 '19 at 11:40
  • $\begingroup$ @user101144 AFAIK ~ and & have never been standard notations in logic. & for conjunction (which C does use) comes from natural language typesetting, not from science typesetting. # wasn't available in all character sets back then and already has a meaning (number) so it would have been confusing to make it mean “not equal”. I don't know where you're taking your idea of “established conventions”, but it doesn't seem to match classical mathematical notations much. $\endgroup$ – Gilles 'SO- stop being evil' Apr 22 '19 at 22:35
  • $\begingroup$ Gilles, I don't understand why you oppose, for I have already explained things. Did you misread? ~ and & are pretty common in logic (and I should know). And I did mention earlier different sorts of subjects where established conventions are the case (e.g. language). I also mentioned something along the lines of making the best of it with the means at hand, so #, the only direct symbol which at least looks like an inequality sign, even if it is a number sign, should work. I know that C uses & for conjunction (and I should know), but I explicitly mentioned "in different contexts" or in ALL. $\endgroup$ – user101144 May 4 '19 at 9:58
  • $\begingroup$ Additionally, C uses the *-symbol in different contexts. Certainly it could have been arranged that, for example, the &-symbol were used in different contexts, or the ~ for all negations, or the # for inequality testing, and the = for both assignment and testing for equality, and so on? $\endgroup$ – user101144 May 4 '19 at 10:00

Not the answer you're looking for? Browse other questions tagged or ask your own question.