let-in-function mutable atomicthread-local dynamic* variable = value;
|2||added 6 characters in body|
What matters about programming languages are the semantics, not the syntax. However, syntax is a vehicle for semantics. It is easy to show that two languages can have incompatible semantics (e.g. unrestricted pointers vs. memory safety, or differences in type systems). Let's focus on the syntax and semantics of variable declarations.
When we declare a variable in some language, this variable has a type, a scope, and a lifetime.
The lifetime of a variable determines how long the value in that variable exists. Afterwards, that value is freed. In many languages, the lifetime is unrestricted: a value may be used as long as it is accessible, the garbage collector takes care of freeing the associated memory. This means we do not statically know when a value is freed. But C++ guarantees deterministic destruction, and it is a frequent idiom to associate sides effects with destruction. This is not possible with garbage collection. This line has wildly different meaning in C++ and Java/C#:
An universal syntax would need precise lifetime control syntax to be able to express a variety of languages.
Next up: scoping. Scope determines where an identifier is visible and the variable can be accessed. There are two kinds of scoping: lexical/static and dynamic. With dynamic scoping, a variable is accessible until a certain point in time, and it is accessible from any code that is executed during this time. Examples are Perl's package-global variables or Lisp's “special” variables. More common is lexical scoping, where the variable is only visible within a specific region of source code. There are three ways where the scope of a variable can start:
Universal syntax would need to provide precise scope controls for a variety of scoping conventions.
Some languages don't make a syntactic difference between assignment and variable declaration. This is problematic when a language features closures, since this prevents us from assigning to closed-over variables.
And there are various other properties such as reassignability, thread-safety guarantees, or constantness of values that might be reflected in a variable declaration. There is no way a simple statement such as Python's
And at that point, our universal syntax is so cumbersome and annoying that no one would want to use it. The solution cannot be to rule out some combinations in order to simplify the syntax, because some language will have used that combination by default. If our syntax cannot express the rich variety of programming language semantics, it is hardly an universal syntax.