Hacker News new | past | comments | ask | show | jobs | submit login
How were the signs for logical and arithmetic operators decided? (retrocomputing.stackexchange.com)
144 points by edent 11 months ago | hide | past | favorite | 36 comments



Most comments there do not go far enough back in time but refer only to later languages that have inherited the operators from other earlier languages.

Regarding the logical operators, in mathematics, many decades before the first programming languages, the symbols were:

  "∧ U+2227;LOGICAL AND" 
  "∨ U+2228;LOGICAL OR"

  Either "∼ U+223C;TILDE OPERATOR" or "¬ U+00AC;NOT SIGN"
Many early programming languages, e.g. Algol 60, CPL, IBM APL\360, used these (Algol 60 used "¬", McCarthy, CPL and APL used "~").

IBM FORTRAN IV (1962) was meant to be used with IBM printers with poor character sets, so it used ".AND.", ".OR.", and ".NOT.".

The next IBM language, IBM NPL (December 1964) replaced the FORTRAN IV keywords with "&", "|" and "¬" (because these symbols were included in the IBM EBCDIC character set, while "U+2227;LOGICAL AND" and "U+2228;LOGICAL OR" were not included).

The next year NPL was rebranded as PL/I and all the languages that use "&" and "|" have taken them directly or indirectly from PL/I.

The languages B and C have taken their symbols and keywords from 3 sources, BCPL, PL/I and Algol 68. The logical operators were taken from PL/I.

By the time of B, ASCII had been standardized and it did not include "¬ U+00AC;NOT SIGN".

Because of this, B had to replace in the PL/I operators "¬" with an unused ASCII symbol, "!".

In B, "&" and "|" were ambiguous, depending on the context they were interpreted as either bit string operators or as "McCarthy AND" and "McCarthy OR".

C has resolved the ambiguity by adding "&&" and "||", and then it has added "~" for bit string not, which had already been used for this purpose in mathematics and in earlier programming languages.


The classic ∧ ∨ symbols from mathematical logic have been used in a few languages, often spelled /\ \/

After CPL they turn up in Miranda (as the weirdly asymmetrical & \/) and in Occam

I thought there were more, but I can’t find them right now.


Fun fact: ASCII added the \ so ALGOL could write /\ and \/!


TLA+ also uses that convention (along with the temporal logic operators [] and <>, and some other unusual conventions like #=).


I like how Python resolves ambiguity.

When you see English text, it works at a high level on objects. If you see ASCII characters, it looks like C, you know you're messing with low level granular elements like you might commonly do in C.


A lot of math symbols are accidental and owe their existence to circumstances of writing, book publishing, typewriter or later computer keyboard. Very few have any kind of history that helps understand their meaning.

Just a few examples: "lambda" in "lambda calculus" was originally the caret sign, which, by convention was used on typewriters because those didn't have Greek letters. Whether Alonzo Church actually wanted the Greek letter or the caret symbol is not known (and he, himself, probably wouldn't care), but if you look at the manuscript, it uses "^".

Minus sign was an attempt to create a sign "opposite to plus", whereas the plus sign was a contraction of Latin "at" (ampersand is another way in which Latin "at" made it into modern typesetting). Multiplication was also an attempt to manipulate the plus sign. And so was division (the horizontal line between two dots, and subsequent mutation into just two dots making a ":" sign).

Asterisk, which used plenty in different mathematical contexts was actually a punctuation sign. Early Roman writing didn't use spaces between words, instead they put dots between them. It was the only punctuation sign they used, so no commas, periods, question marks etc. All that stuff came almost a thousand years later.

A bunch of logical signs were invented by Frege and later popularized / amended by Wittgenstein. These were completely artificial and didn't derive from anything. I don't think the authors ever explained why they chose any specific shapes, but my guess would be that they were looking for something visually distinct enough for a small alphabet they created and arbitrarily assigned symbols to operations.


Interesting post but I think you're wrong in the following sentence:

A bunch of logical signs were invented by Frege and later popularized / amended by Wittgenstein.

Jan Von Plato goes into this in The Great Formal Machinery Works. Frege's notation never become popular - his notation involved lines from one part of an expression to another (!) and is fairly incomprehensible. A more or less modern system of symbols of mathematical logic was created by Russel and Whitehead in Principia Mathematica extending the symbols of Peano (but using the ideas of Frege). Russel and Whitehead syntax, ("there exists" and "for all" symbol) was taken up by Hilbert and the Gottingen school which crafted a lot of the basic theories of mathematical logic. Von Plato doesn't refer to Wittgenstein influencing notation and I don't think he did - he was a popular but idiosyncratic philosopher, not a mathematician.

Von Plato's history of mathematical logic in Great Formal Machinery... is fascinating.

Edit: Wikipedia describes Frege's notation. You have draw lines connecting expressions, an approach that quickly gets unwieldy. I believe that only Frege used Frege's notation. Wittgenstein refers to Frege but that's it.

https://en.wikipedia.org/wiki/Begriffsschrift


To the best of my knowledge, Wittgenstein lived with Russel for quite some time and was a very influential force in writing the Principa. I believe I saw a lot of prototypes of the modern logical symbols in his Traktatus.

I also believe that Russel traveled to meet Frege in his quest for writing the book. He definitely saw his work even before it was published / had private conversations with him face-to-face. Not sure how much of the invented language made it into Principia, but the author was definitely familiar with Frege's work.


All I know is Von Plato and some random readings in foundations for my degree, but this[1] seems to indicate Russel met Wittgenstein after Principia was completed.

I also believe that Russel traveled to meet Frege in his quest for writing the book.

No doubt, as I said above, Principia was very influenced by Frege's ideas. But it absolutely did not use Frege's notation(which was a disaster as I describe above). Von Plato really emphasizes how much of an advance the notation of Principia was. And seriously, it's remarkable how new modern mathematical logic notation is, it didn't have true modern form 'till the 20s or 30s.

[1] "It was October 1911, volume one of Principia Mathematica was newly out, and Bertrand Russell, fellow of Trinity College, Cambridge, was having his tea when a young man suddenly appeared. He introduced himself as "Loot'vig Vit'gun-shteyne". https://www.independent.co.uk/life-style/when-ludwig-wittgen...


That Wikipedia section is uncharacteristically bad. It doesn’t even define or explain the notation, it’s just some examples and a long quote. I’m sure that there was more to it than that.


The German version has more details and better explanations.


Minor nitpick: "And" in latin is "et", as in "et al.".


Yes, whoops.


> the plus sign was a contraction of Latin "at" (ampersand is another way in which Latin "at" made it into modern typesetting)

An ampersand is et [and], not at [but]. There are still current forms of the symbol that are transparently just a T attached to an E.

I was about to ask how the plus sign could possibly be related to the word "but", but I'm guessing you meant that it derives from et too?


> A bunch of logical signs were invented by Frege

This is true. I find Peirce's existential graphs interesting because they permit stating existential and universal quantifiers without any explicit syntax! Frege's work evidently has priority by about 4 years, but it doesn't appear that Peirce was aware of it.


Bob Bemer, one of the principals of the development of ASCII, argued that the backslash should be incorporated so that “and” (∧) could be written as /\ and “or” (∨) as \/. The logic signs are derived from the Latin ac (or atque, “and”) and vel (“or”), respectively.


Is there any other symbol that has caused as many problems as the backslash, in computing?


Yes: space. It started with FORTRAN so the history is quite long.


I asked a question about the origins of the XOR operator a while back.

Ken Thompson was emailed by the accepted answerer and provided a response, in fact!

https://softwareengineering.stackexchange.com/questions/3313...



I'm not sure XOR/^ was added by Ken himself because it is not in his original B language and while the earliest C compiler can parse it, it can't generate code for it. I think it was Steve Johnson or Dennis Ritchie. Now B originally did have a ^ but that stood for OR because | was in the lower case region of ASCII.


I find it unfortunate that so many programming languages (e.g. JavaScript and Python) that purport to support Unicode identifiers actually exclude the most visually distinctive Unicode characters (i.e. symbols and some emojis) from being used in identifiers, on the entirely specious grounds that they are not Unicode word characters. For example, there are legitimate reasons why one might want to use the mathematical symbols for intersection and union as names of functions, or use circled letters/numbers as/in variable names, but you can't do these things because those are symbols and not Unicode word characters.

If you are going to allow Unicode, you should just default to the simplest, most easily memorizable rule (i.e. allow all characters except for ASCII non-word characters). Trying to be helpful by excluding characters you cannot imagine why anyone else might want to use just makes the rule harder to memorize and limits the class of well-former identifiers for no good reason.


I once adapted a pre-Unicode compiler (for a weakly-specified dialect of Basic) to accept non-ASCII identifiers in exactly the fashion you suggest. It worked fine, because almost nobody took advantage of the feature, and the myriad avenues for confusion went unexplored. I would not make the same choice today.


Ha! In a way I think that lends support to my suggestion. Allowing all non-ASCII Unicode characters has both positives and negatives. But the negatives are largely negligible, for precisely the reason you mention: most people will not take advantage of that feature (Swift, for example, allows emoji identifiers, but it's extremely rare to find emoji identifiers in actual Swift source code), so the potential for confusion is minimized. On the other hand, the positives (for a small minority of programmers who prefer them) are very real.


Before ASCII, languages didn’t necessarily mandate what characters to use for operators and other symbols. They defined an abstract syntax, but left it to the implemention for a particular machine what chracters to use for a given symbol, because of the large variation in keyboards and character sets across machines.

I believe Algol and BCPL did it like that, and C was one of the first languages to specify the exact characters to use for its symbols.


More than that; ALGOL-68, for instance, allowed for translating keywords into different national languages, IIRC.


Yes, this is the same feature. The “abstract token” like “if” is used in the language specification and BNF but in the compiler implementation it could be represented by different characters.


I had been guessing * made its way into character sets because of its business use as a line fill for printed checks. (for those of you not alive in the 20th century, see https://en.wikipedia.org/wiki/Cheque )

Edit: then again, it's in the 0x28-0x2F range along with + - and /, which suggests it was already thought of as mathematical as early as 1963...

Edit 2: it doesn't seem to occur in ITA-2, and in FIELDATA it's alongside punctuation like & $ ( and %.


Perhaps for the reason proposed by you, the IBM typewriters had "*" but they did not have "× U+00D7;MULTIPLICATION SIGN".

This has forced the choice of "*" for multiplication in Fortran, in 1956. All the other languages that use "*" have taken it from Fortran. There are only a few exceptions, like Algol 60 and APL\360, which used "×", because they did not care about what the standard IBM printers supported.

The ASCII encoding is irrelevant, it was chosen more than a decade later and the earlier character sets had encoded "*" in completely other locations.


Smalltalk uses ^ for return and _ for assignment (aliased to := in esentially all implementations for obvious practical reasons) because in draft version of ASCII these two characters were ↑ and ←.


No mention of APL here or on retrocomputing. We had a decwriter at uni in the 70s/80s timeframe with APL key caps which was always the last terminal available to login to the Dec-10.

IMP (the Edinburgh programming language behind EMAS) used %op% notation which is very like early Fortran .and.

To repeat my comment from the earlier posting, 7 bit ASCII and upper case only terminals meant limited symbols were available universally. Using "." for multiplication would have made parsing decimal fractions and floating point numbers significantly harder despite the commonplace availability of full-stop in the character set to hand. Thus use of

  a . b
as the nearest available notation to

  a • b
(Using unavailable characters of the time, • not being in 7 bit ASCII) So

  a * b 
Seems logical. Remember that six bit byte notation was also in use for BCD. Even less characters.

ASCII is a neologism for IA5 and the Baudot codes available before ASCII happened. People who worked on that standardisation process are still around, and active as are people who worked on early Fortran if not the ground states.


In an ideal world, of course, symmetric operators would have symmetric symbols, non-symmetric operators asymmetric symbols ... and antisymmetric operators what kinds of symbols?


Interesting! Just for fun I tried to list all binary operators to check which comply with this rule.

These symmetric symbols represent symmetric operators in one or more widespread languages (C-like, Basic, etc.), so they're OK:

  + * | ^ /\ \/ == === <> =
(where = is test for equality, not assignment).

Conversely, these asymmetric symbols represent asymmetric operators, also OK:

  / % -> => << >> < <= > >= , := \ &&
plus all the assigments like +=.

Now the bad ones, symmetric symbols for asymmetric operators:

  - = ** ^ || . :: ..
(where = is assignment, ^ is exponent).

And finally the few asymmetric symbols for symmetric operators:

  & !=
I'm probably missing a lot of other operators...


> and antisymmetric operators what kinds of symbols?

Probably horizontally (flip-)asymmetric but 180-degree rotationally symmetric. With negation-like operators being vertically flip-symmetric.


Fortran has .and. and .or. for logical operators, which is pretty easy to remember.

& seems pretty obvious, of course they couldn’t have known at the time that logical operations should probably be given priority over bitwise ones.

| is an odd symbol. They don’t really justify it in the stack overflow answer, just mention where it came from.

Unix pipe, conditional probability, and or. I guess a vertical line is naturally going to be very popular though.


The early character sets that were available in teletypes and line printers were not selected with the purpose of writing mathematical notation, but with the purpose of writing "business correspondence".

Because of this, the authors of most early programming languages, with the exception of APL\360 and of some European programming languages, which were not restricted to the IBM business-oriented character sets, had to replace the traditional mathematical symbols with whatever "business" characters were more suitable.

There is nothing odd about "|". It was included in the "business" symbols, for drawing tables. Among the few available symbols, it was doubtless the most appropriate choice for "OR".




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: