3

When I was a beginner it took a while to learn the language syntax and the idea that languages couldn't improve after they were invented.

But now we're seeing new language features added every year with ES5, ES6 the so on.

If I don't write software for a few weeks or months when I come back to it I have often found for the first few days found myself writing if statements with the literal words and and or.

if (isSinglePost and isLoggedIn) {
   // do something
}

AND I've seen other languages use literal and and literal or in their language syntax.

I'd like to have the option to use and and or or || and &&. I'm not saying it's the best practice but it would be nice to have that option for readability and writability.

So now I'm wondering is there any reason languages didn't use and and or in their language syntax in the first place when they were invented? And would there be any negatives to adding it now?

ES2019candidate

5
  • 5
    But some languages do. VisualBasic, several flavors of SQL, IBM's EGL, etc. all use "if condition and condition" Also, some languages support both,and mixing them will cause issues with operator precedence and such.
    – ivanivan
    Mar 4, 2019 at 19:38
  • Larry Wall was once asked about his use of punctuation as names for Perl's built-in variables (e.g., $_ as the topic variable) and replied that "Perl provides word-oriented aliases to all of these variables, if you choose to write COBOL in Perl. Oddly, most folks don't."
    – Blrfl
    Mar 4, 2019 at 19:58
  • 6
    Because the operations aren't called "and" and "or". The boolean operators are conjunction and disjunction, and only colloquially called "and" and "or". In math ∧ and ∨ are used as symbols to denote those mathematical operations.
    – Polygnome
    Mar 4, 2019 at 20:17
  • @Polygnome the reality is that && and || are usually more like control flow operators like ? : than they are like logical operators. There's nothing special about the way this operator is written in the field of logic.
    – amon
    Mar 4, 2019 at 20:50
  • 2
    Personally, I think this would make it harder to quickly parse longer boolean statements. I mean, we could condense anything to plain English. Quick, what's "(five plus six minus one) times ten plus twenty times two"? Or, as you probably can read more quickly "(5+6-1)*10+20*2".
    – Clay07g
    Mar 4, 2019 at 20:52

7 Answers 7

19

In short

It's historical reasons.

The long history

Many older languages created between the 50's and the end of the 60's, as well as used the logical operators that you like such as not or and and:

  • Fortran II, 1961, introduced logical operators between dots with .NOT. .AND. .OR.
  • BASIC, 1964, (although I'm not sure that it had these operators in the very first version)
  • Simula 67, used them as keywords for the more concise and mathematically inspired ¬ for not, (and=intersection) and (or=union).
  • Algol68,1968, used them as a portable alternative to ¬, and
  • Pascal, 1970,

Their modern descendants (e.g. ADA) have kept this keyword style.

You can however see that already in this first list, there was a quest for concise expressions in many languages. But the character sets in those years were not portable and the later work on the ASCII character set didn't let many of the special characters survive.

Other languages used also the concise approach but chose characters that were more lucky in the standardisation process (for example see here the rationale that lead to the inclusion of | in the ASCII character set):

  • PL/I, 1964, used & for and, | for or and ¬ for not
  • BCPL, 1967 used & for and, | for or and ~ for not. It also offered keyword alternatives. But those were not so appealing: LOGOR, LOGAND and LOGNOT
  • Finally came C, 1972, that had the incredible growth that we know. C was inspired (indirectly via B) from BCPL. It is not surpriseing that its authors, Kernighan & Ritchie, took over the & and |. But as C is system oriented these were taken as bitwise operators. K&R identified also the need to have short circuit operators for conditional expressions to know that they can skip the rest of the expression if it's already known that it's true or false (the purpose was to write concise error checking conditions). And for these logical operators, they just doubled the symbol, so && and ||

Then came C++ inspired by C, then Java inspired by C++ then JavaScript inspired from Java... and this is why nowadays so many languages have opted for the well known || and &&

P.S.: Note, that if JavaScript would have adopted and or rather than && || , it would probably have adopted begin .. end rather than { .. } , making it overall a lot more verbose than we are used to ;-)

P.S.2: Note, that psshill points out in comment that C++ funilly supports and, or, bitand, bitor and a couple of other alternative tokens. But nobody uses them. Interestingly, these are not a recent language features: Stroustrup explains in his book "The design and evolution of C++" that these keywords were introduced by the C++ ISO committee in November 1993, because in that pre-unicode world, ISO-646 used the ascii code of []{} and | to map European characters, which made C++ very complex on terminals using this encoding. Strangely, though, there is no begin ... end to replace {...} and instead <% and %>. I guess that the alternate keywords not really won traction, because around the same period ISO-8859 encoding started to be used with all ascii characters available. Usage and habits did certainly do the rest: Stroustrup reports highly controversial discussions around alternative tokens.

2
  • 2
    Fun fact: Both C and C++ allow using and, or, ... instead of &&, ||... In C, these operators are macros (iso646.h) and in C++ these operators are built into the language. See en.cppreference.com/w/cpp/language/operator_alternative
    – pschill
    May 17, 2019 at 9:26
  • @pschill Great point ! Never realised that these alternate keywords were available :-). So I looked for the origin, and it was worth an edit. In short: they were introduced to cope with the old ISO646 character-set that misused some ASCII codes and resulted in unreadable C++ code on older terminals. But around the same period ISO8859 was available which solved the problem. I guess the majority of programmers kept the old style; Those who would really have needed the alternative either bought newer terminals or used PCs anyway, and preferred to stick with the community's practices.
    – Christophe
    May 17, 2019 at 18:22
9

C picked some operators, and most C-like languages stuck with it. Most, but not all. A few also mixed in some Basic-ish and Pascal-ish traditions.

  • C++ has equivalent tokens for these operators. The token and is parsed as &&, and or is parsed as ||. However, the use of these is highly frowned upon.

  • Perl has both an and and && operator. These behave the same but have different precedence level in the grammar, which often makes the low-precedence versions easier to use. For example, the following two statements are equivalent:

    open(my $file, '<', $filename) || die "Could not open $filename: $!";
    open my $file, '<', $filename or die "Could not open $filename: $!";
    
  • Python prefers alphabetical operator like and, and does not have a symbol version. Syntactically, the language does not belong to the C family, though.

While new languages can introduce new operators, it is not generally possible to retrofit them into an existing language. While a language evolves it must ensure that it stays backwards compatible. This is especially important for a client-side scripting language like JavaScript that cannot mandate by which engines it will be executed. Some changes are safe when they do not clash with existing syntax, but introducing new keywords is extremely tricky: you cannot retroactively outlaw code like function and() {}. This gives rise to concepts like contextual keyword, but they complicate parsers and therefore also downstream tooling.

However, JavaScript has a good story for development-time syntax extensions through build-time transpilers with things like Babel. If you want your pretty keywords you can write your code with these keywords, but let a transpiler replace them with standard JavaScript before deploying.

4
  • "However, the use of these is highly frowned upon." - Citation required. While it's true that hardly anyone ever uses the alternative operators in C++, I've never seen anyone who thought that they are really a bad thing. Mar 5, 2019 at 10:36
  • @ChristianHackl searching for opinions on the C iso646.h header or C++ alternative tokens usually brings up strong opinions in either direction. While I would actually prefer that syntax, I'm strongly in the “no one should ever use this” camp simply because it is an arcane, little-known feature that would bring more confusion than clarity. Mentioning such a feature without discouraging its use would have been irresponsible. If you want a citation, then the Google Styleguide says no, but that's hardly authoritative.
    – amon
    Mar 5, 2019 at 11:53
  • 2
    Yeah, the Google Styleguide is only meant for Google's own (legacy?) code and should not be taken as an appropriate styleguide for C++ in general. That misunderstanding used to pop up all the time in Stack Overflow questions. I sort of agree with your opinion on the operators, I just believe that "highly frowned upon" is speculative. I believe it's more like a total lack of interest by the community than active discouragement (compared to things like, say, goto or C-style casts). Mar 5, 2019 at 12:10
  • 2
    @ChristianHackl: The same issue comes up all the time with regard to the AP Style Guide and English language usage. Part of the intention of the AP Style Guide is to remove any element of individual style from a person's writing, so that stories by different reporters can be used interchangeably. In most contexts, however, writers should want to have a style which doesn't perfectly match everyone else.
    – supercat
    Mar 5, 2019 at 16:48
4

The biggest problem would be the backwards compatibility issues that would arise if you took a previously unreserved keyword and made it reserved. For example, in any language that does not have a symbol prefix for variables (like the "$" in PHP), you cannot easily just go add a new reserved word because older programs might have used that phrase as a variable name. In some languages, the compiler might be smart enough to infer if you are meaning a variable name versus a reserved keyword name, but that adds a lot of effort to the compiler itself.

3
  • Are there any existing contexts in which one could have two valid expressions separated by an alphanumeric identifier? In C that would be possible if e.g. one were to say #define foo *; one could then have two valid expressions separated by the identifier foo. I don't think that would be possible in Javascript, however, unless the identifier was preceded and followed by line breaks, in which case the keyword wouldn't be usable as an operator anyhow.
    – supercat
    Mar 5, 2019 at 16:52
  • I think JavaScript could easily be the most dangerous language to make such a change in, given its dynamic nature and no real compiler to target, just a slew of browser makers to convince of the new features.
    – GHP
    Mar 5, 2019 at 19:52
  • Fair point, but I think the issue isn't with reserved words, but rather the fact that in dynamically-programmed contexts, the fact that a piece of text isn't syntactically valid code may in and of itself be semantically significant.
    – supercat
    Mar 5, 2019 at 20:10
2

Even if the language definition specified your and and or keywords rather than the more mathy |, ||, &, and && keywords introduced by the C language folks at Bell Labs (Brian Kernighan and Dennis Ritchie of blessed memory), we'd still need more detail than and and or can give us.

 if ( expensive_function (a) && another_expensive_function (b) ) {}

skips evaluating the second expensive function if the first one comes back false. That's also important because it lets us write safe code.

 if ( a != 0 && 1.0 / a > 0.3) {} 

would sometimes throw div-by-zero if a is zero if we used & in place of &&.

But

 if ( expensive_function (a) & another_expensive_function (b) ) {}

always evaluates both functions. The distinction is important if the second function has any side-effects (like printf() for example).

Other languages have different ways of spelling && and &. But the distinction between the two still exists. E.g. in VB.net, AndAlso functions as && does in c-like languages.

SQL gets away with using AND and OR because it's a declarative language, not procedural. It's almost, but not quite, a side-effect-free language. So SQL query planners can decide which parts of anded / ored queries must be evaluated, without we programmers telling them.

7
  • VB handles this with its "And" and "AndAlso" operators.
    – GHP
    Mar 4, 2019 at 20:42
  • In C++ and, bitand, or, bitor are legal and working alternatives to &&,&, || and |. C has a standard header defining them as macros. So giving it as an example of how it is a problem is a bit weird.
    – Frax
    Mar 4, 2019 at 20:50
  • 1
    +1 for this Interesting contribution that highlights very well the increase precision of & and && compared to and, and the principle of the short circuit operators. One remark however: while K&R are behind the notion of short circuit, the use of the mathy symbols precedes C by 10 to 15 years, since | was already used in PL/1 begin of the 60’s and that was one of the reason that helped this rather spartiate character to end up in the ASCII character set that was made available to K&R.
    – Christophe
    Mar 5, 2019 at 8:55
  • DELETE FROM x or DROP TABLE foo is declarative and almost side-free? I don't think so. Mar 5, 2019 at 10:42
  • 2
    @ChristianHackl: The component expressions are side-effect free. The query is not.
    – Ben Voigt
    Mar 6, 2019 at 2:02
0

It all goes back to primarily C. C was launched as a thin layer over assembly language, maintaining unsafe coding.

As you know in assembly language bit masks, bit ANDs and ORs, are important. Hence the need for the bit operators & and |. Typically:

#define A_BEZ (A_LEFT | A_CENTER | A_APPROX)

Then there were the short-cut operators and-then and or-else: && and ||, for such things like:

if (i < n && a[i] < k)

A more or less predictable choice doubling & and | seeing ++ and --.

Both schools run partly side-by-side:

  • symbolic expression operator: &&, ||, %, ~?~:~

    Advantage: mathematical (∧, ∨)

  • named expression operator: and, or, mod, if(~)~else~

    Advantage: not cryptic (and, or)

Named operators are nicer looking especially for boolean expressions, hence and and or reentered C. It is worth comparing them with Algol68 styles. An outstanding language wherein everything is a (typed) expression.

INT a := ...;                          # REF INT variable a becomes ... #
INT b := ...;
IF a < b THEN a ELSE b FI := ...;      # Assigment to a condition LHS #
(a < b | a | b ) := ...;
(node = nil | list.head | node.next ) := ...;
BOOL c = a = b OR IF i < n AND IF v[i] < a THEN b > a ELSE  a < v[i] FI;
BOOL c = a = b ∨ ( i < n ∧ v[i] < a | b > a | a < v[i]);

Above | is a separator for then/else (else-if, ELIF, had |:), FI the end-if.

One sees that Algol68 was not afraid to use mathematical symbols not apertaining to ASCII, and even a bold font for keywords and types/operators: and. In reality AND or .or. was used as even then special keyboards were rare (simple terminals rather).

In short:

&& and || were the short-cut versions of the bitwise/both-sides-logical & and |.

Some future language may well reconsider this, as also and an or appear.

6
  • 1
    "C was launched as a thin layer over assembly language, maintaining unsafe coding." - Isn't it rather true that C was launched as a high-level, machine-independent language to improve coding safety? Mar 5, 2019 at 10:44
  • @ChristianHackl yes "as close to the machine" though. No index checks, "everything" a pointer, a char* (even a char[80]), cross-type casts, zero terminated strings. Not as high as even a simple Pascal. But you could program everything, on really many platforms, and port the code to other platforms. Much better than assembler, though neither suited imho as teaching sample language & its constructs, nor for robust productive code. (And I do love Unix.) C led to / was the excuse for Ada for instance. Do not get me wrong, I love C.
    – Joop Eggen
    Mar 5, 2019 at 11:14
  • @ChristianHackl: Properly written programs would be safe, but any safety was the responsibility of the programmer, not the language.
    – supercat
    Mar 5, 2019 at 16:43
  • @JoopEggen: In the late 1980s, C wasn't so much a "language" as a recipe for producing a family of dialects for different platforms that used a common syntax, but with semantics adapted for each target. It's too bad that the authors of the Standard tried to treat it as a language which didn't define anything could vary between platforms, rather than recognizing that the platform-dependent behaviors were a fundamental part of the C "recipe".
    – supercat
    Mar 5, 2019 at 16:45
  • @supercat a time of very different mainframes, elite firms, very heterogeneous hardware. That an int somewhere was an 22 bits ones-complement was to be taken into account. The POSIX standard also slowly grew. What a time.
    – Joop Eggen
    Mar 6, 2019 at 7:23
-1

In general, people maintaining language standards are loath to add features that would encourage programmers to write programs that are incompatible with existing implementations except in cases where code that uses the new features could be in some meaningful way superior to anything that could perform the same task on the older implementations (or could accomplish some task that simply couldn't be done before). I don't see the addition of text-based operators like and and or as offering enough value to overcome that, as much as I like text-based operators (using text-based operators for things like integer division, modulus, and remainder operators would allow programmers to select the exact operation they need without having to kludge it).

-1

There are problems with natural languages.

Just take your question as an example. If we read it carefully, as a compiler would do, the correct answer is: “But most languages do. The only exception that I remember is Pascal”.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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