Why in nearly all modern programming languages (Go, Rust, Kotlin, Swift, Scala, Nim, even Python last version) types always come after the variable declaration, and not before?
Your premise is flawed on two fronts:
- There are new-ish programming languages that have the type before the identifier. C♯, D, or Ceylon, for example.
- Having the type after the identifier is not a new phenomenon, it goes back to at least Pascal (designed 1968–1969, released in 1970), but actually was used in mathematical type theory, which starts ~1902. It was also used in ML (1973), CLU (1974), Hope (1970s), Modula-2 (1977–1985), Ada (1980), Miranda (1985), Caml (1985), Eiffel (1985), Oberon (1986), Modula-3 (1986–1988), and Haskell (1989).
Pascal, ML, CLU, Modula-2, and Miranda all were very influential languages, so it is not surprising that this style of type declarations stayed popular.
Why x: int = 42
and not int x = 42
? Is the latter not more readable than the former?
Readability is a matter of familiarity. Personally, I find Chinese to be unreadable, but apparently, Chinese people don't. Having learned Pascal in school, dabbled with Eiffel, F♯, Haskell, and Scala, and having looked at TypeScript, Fortress, Go, Rust, Kotlin, Idris, Frege, Agda, ML, Ocaml, …, it looks completely natural to me.
Is it just a trend or are there any really meaningful reasons behind such a solution?
If it's a trend, it's pretty persistent: as I mentioned, it goes back a hundred years in mathematics.
One of the main advantages of having the type after the identifier, is that it is easy to leave the type out if you want it to be inferred. If your declarations look like this:
val i: Int = 10
Then it is trivial to leave out the type and have it inferred like this:
val i = 10
Whereas if the type comes before the identifier like this:
Int i = 10
Then it starts to get hard for the parser to distinguish an expression from a declaration:
i = 10
The solution that language designers then usually come up with is to introduce a "I don't want to write a type" keyword that has to be written instead of the type:
var i = 10; // C♯
auto i = 10; // C++
But this doesn't actually make much sense: you basically have to explicitly write a type that says that you don't write a type. Huh? It would be much easier and more sensible to just leave it out, but that makes the grammar much more complex.
(And let's not even talk about function pointer types in C.)
The designers of several of the afore-mentioned languages have weighed in on this subject:
Note: the designers of Ceylon also documented why they use prefix type syntax:
Prefix instead of postfix type annotations
Why do you follow C and Java in putting type annotations first, instead of Pascal and ML in putting them after the declaration name?
Because we think this:
shared Float e = ....
shared Float log(Float b, Float x) { ... }
Is simply much easier to read than this:
shared value e: Float = ....
shared function log(b: Float, x: Float): Float { ... }
And we simply don't understand how anyone could possibly think otherwise!
Personally, I find their "argument" a lot less convincing than the others.