There is some historical precedent for what you said. The first programming languages were assembly languages, which only have statements that you write one per line. You can sort of say that each instruction name is a "keyword".
mov eax ebx
jump 1235
xor eax eax
The first big programming language with expressions was Fortran. Its expressions were for mathematical formulas. Everything else was a statement that you still had to write one per line (and in under 80 columns, to fit in a punch card).
Part of the reason fortran was like this is that parsing algorithms were quite primitive. Ideas such as lexing, "tokens", and context-freem grammars, which are standard today, weren't common back then. For example both of the following were valid ways to start a loop in Fortran. Note the lack of whitespace in the second!
do i = 1, 10
doi = 1,10
Moving on, as compiler writers got better at parsing it became more popular to allow free formatting in programming languages. Instead of mandating one statement per line, use semicolons as statement terminators and let you format it as you see fit. Over time this led to a blurrying of the distinction between statement and expression. For example, in C and Javascript many things that used to be statements are now expressions (one notable example being assignments). This is taken the furthest in functional programming languages, where almost everything is an expression.
That doesn't really work, since `alert("Hello, World!")` or `doSomething()` are usually statements, not expressions; while `new SomeFunction()` is usually an expression, as is `'abc' in ['abc']`
I think that, in the context of JavaScript, if you want a "quick and dirty" way to differentiate them, the `console.log( /* put thing here */ ) ` idea from the article is the best way to go - if you can validly put the thing there, it's an expression, otherwise it's a statement.
My point was that GP's rule of thumb (if it has a keyword, it's a statement, otherwise is an expression) is wrong on both ends.
A JS program is composed out of statements, which may contain expressions. In particular, in JS, any expression is also valid as a statement. This is not true in all languages (for example, `2` is not a valid statement in Go).
> My point was that GP's rule of thumb (if it has a keyword, it's a statement, otherwise is an expression) is wrong on both ends.
I do agree!
Sorry to bother you but I am a bit confused about this part of your comment:
> `alert("Hello, World!")` or `doSomething()` are usually statements, not expressions;
Can you please clarify what you mean here? Do you mean `alert("Hello, World!")` is an expression? Or do you mean it is not an expression? Or did you mistype?
Your `console.log( /* put thing here */ )` test is a pretty good one and indeed `console.log(alert("Hello, World!"))` passes this test.
I meant that you would usually encounter those as statements, as in the following example:
function foo() {
alert("Hello, World!");
doSomething();
}
And not as expressions (as in your example of `console.log(alert("Hello, World"))`.
Btw, a better rule of thumb for JS is "if you can add `;` after it and not alter the meaning of the program, it's a statement; otherwise it's an expression".
I wouldn't say that's abuse and I missed that many many times in JS/TS, for example on unreachable variants in tagged enums. This usually turns into null with a null check afterwards just to throw the exception, which is more verbose for no reason.
With this definition, it's easy to see that, if the syntax starts with a language keyword, it's a statement.
BTW, language functions (like 'Array.join()') are expressions because they don't start with a keyword.