10

This question already has an answer here:

C, C++, C#, Java, as well as many other statically typed languages have the type before variable like (int a =5, auto c = 4, etc.).

Non-statically typed languages (such as Javascript, basic) use var (or let) before the name (var a = "asd")

Why does Kotlin, a statically typed language, use a mixture (var i: Int)?

Why not define it as (Int i = 5)? It's a bit less typing and I don't see the advantage in form #2?

marked as duplicate by Bart van Ingen Schenau, Thomas Owens Mar 3 '17 at 11:27

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 3
    Your assumptions are incorrect. Other statically-typed languages follow the same convention, for example Scala. – Andres F. Mar 3 '16 at 23:03
  • 3
    TypeScript also follows this convention. – Robert Harvey Mar 3 '16 at 23:03
  • 6
    Not to mention, Standard ML, Ocaml, Haskell and Swift. – Doval Mar 3 '16 at 23:17
  • 7
  • 4
    It is not a question of dynamic vs static. Languages based on C syntax have type before identifier because this is how C did it. But many static languages have type after the identifier. So it comes down to the question if the language should "look like C" or not. Java follows the "look like C" tradition, so in order to offer improvements over Java, Kotlin has to break with the C tradition when they think it can lead to improved syntax. The advantage of type-after-identifier is it can support type inference in a nicer way. C did not have type inference, so it wasn't an issue for C. – JacquesB Mar 4 '16 at 15:27
16

From Kotlin's FAQ:

Why have type declarations on the right?

We believe it makes the code more readable. Besides, it enables some nice syntactic features, for instance, it is easy to leave type annotations out. Scala has also proven pretty well this is not a problem.

By "readability" it's likely Kotlin's designers meant the same thing Odersky meant for Scala: that by writing the identifier first, you emphasize its name over its type. Odersky argues that this doesn't matter much for short type names such as Int, but matters more when you have SomeLongType<OfOtherLongType>. In his words:

val shapeInfo: HashMap[Shape, (String, String)] = makeInfo()

It says clearly

  • We define a value here, not a variable or method (val)
  • The name of the thing we define is shapeInfo
  • If you care about it, here's the type (HashMap[...])
  • 1
    Not convincing. Remove String in the second example and it collapses to var foo = "hello", just like the first example did. – Robert Harvey Mar 3 '16 at 23:58
  • 1
    @RobertHarvey: var/let in Swift is very useful. – gnasher729 Mar 4 '16 at 0:23
  • 3
    @RobertHarvey: And the question was: Why does Kotlin do X? "Because Scala does X" is a reasonable answer. "Because C# doesn't" isn't. – gnasher729 Mar 4 '16 at 0:24
  • 1
    @gnasher729: The OP was the one who mentioned C# first, not me. It's not unreasonable to make the C# comparison when it was the OP that floated the comparison in the first place. – Robert Harvey Mar 4 '16 at 0:40
  • 1
    @Jon Ok, I thought some more and removed the example, simply leaving the quotes by Kotlin's and Scala's designers. – Andres F. Feb 24 '17 at 13:31
13

C, c++, C#, Java, as well as many other statically typed languages have the type before variable like (int a =5, auto c = 4, etc).

First off: language design is not a popularity contest.

But even if it were, Kotlin would probably be on the winning side: Pascal, Modula, Modula-2, Oberon, Oberon-2, Modula-3, Ada, Eiffel, ML, Caml, OCaml, F#, Haskell, Miranda, Go, Scala, Idris, Frege are just a few of the languages I can name off the top of my head, and there are many others.

Non-statically typed languages (such as Javascript, basic) use var (or let) before the name (var a = "asd")

And others don't, like Python or Ruby.

Why not define it as (Int i = 5)? It's a bit less typing and I don't see the advantage in form #2?

There are lots of advantages. Some are:

  • Familiarity: lots of languages have the type after the identifier. By following their lead, Kotlin will be immediately understandable by programmers who have experience in one of those languages.
  • The syntax for Type Inference is easy: just leave out the type, it will be parsed just like it was before, just without the type. If you have the type before the identifier, then leaving it out changes how it is parsed (assuming we parse left-to-right). This means that you either need a more complex syntax, or you need a "fake" type which the programmer must use to explicitly indicate that the type is implicit (which is kind of ridiculous). C++ (auto) and C# (var) have this problem, for example.
  • 3
    +1 for 'language design is not a popularity contest.' – marstato Feb 24 '17 at 14:28
6

It's because when you have higher-order functions (functions that can take other functions as parameters, or return other functions) then having the type after the variable makes your type declarations read left to right instead of in a weird spiral.

Consider this example from an excellent blog about why golang went this route:

int (*fp)(int (*ff)(int x, int y), int b)

It's pretty difficult to tell what's a return type and what's an argument, and you need parentheses to disambiguate a lot of that. It's a major reason why people avoid function pointers like the plague in C. With the type at the end, that ambiguity is removed without parentheses.

As amon pointed out, recent C-family languages do this more like:

std::function<int(std::function<int(int x, int y)> ff, int b)> fp

Yes, the ambiguity is removed here as well, but it was for the C example too. We have just chosen a different set of delimiters (the std::function<>) to disambiguate. We still have a special syntax for declaring function pointers that's outside of the regular type declaration syntax. We no longer read in a spiral, which is a vast improvement, but we haven't even added generics into the mix and we already have a pretty long and busy type signature.

Compare with the postfix type signature for a function declaration:

def f(ff: (Int, Int) => Int, b: Int): Int

This reads very cleanly, from left to right. I can scan down the left side of the page and easily find my function names. It's easy to parse, because you already have a declaration, you just add an optional : type signature at the end. Declaring a variable holding a reference to this function is nearly identical:

val fp: (ff: (Int, Int) => Int, Int) => Int = f
// although usually because of type inference you can just write:
val fp = f

We are also using a colon here as a delimiter to resolve the ambiguity, but the delimiter on the other side was already there, either the comma or the closing paren or whatever token, so it is much less obtrusive. This is simply not possible with type-first. You have to surround the function declaration, one way or another.

When you use higher-order functions all the time, every bit of added readability helps. That's why languages that intend to idiomatically support higher-order functions at some point use type-last syntax from the beginning.

  • 1
    What would the example you provided look like in the new form? – Robert Harvey Mar 3 '16 at 23:57
  • 1
    Are you certain that this is the answer? or is it one of many possible reasons that it uses such an approach? – user40980 Mar 4 '16 at 1:24
  • 5
    This is true for C, and the circumfix type syntax has largely been recognized to be a mistake. However, other languages imitate C or Algol and put the type before the variable name without this insane circumfix syntax, e.g. Java or C#, or even C++ without the C subset. None of these have problems with higher-order functions, e.g. modern C++ might write std::function<int(std::function<int(int x, int y)> ff, int b)> fp which has none of the ambiguities you mentioned. – amon Mar 4 '16 at 10:04
4

It is not a question of dynamic vs static. It is a question of "looking like C" and "not looking like C". The languages C++, Java, and C# have followed the tradition of "looking like C" for the sake of familiarity. Other languages, static or dynamic have chosen different syntaxes.

The type-before-identifier syntax has the disadvantage that it doesn't work as nicely l with optional type annotations. C did not have type inference, so it wasn't an issue. C# did initially not have type inference ether, so when it was added it led to a somewhat inconsistent syntax. The advantage is that it "looks like C", so is initially more familiar to developers, even if objectively not as logical a syntax.

Java follows the "look like C" tradition, so in order to offer improvements over Java, Kotlin may break with the C tradition in cases where they think it can lead to improved syntax. (If familiarity were the only thing that mattered, there would be no justification for Kotlin in the first place)

1

C, c++, C#, Java, as well as many other statically typed languages have the type before variable like (int a =5, auto c = 4, etc).

This is true, but far from the whole story. There are also quite a few statically typed languages such as Pascal, Delphi, Ada, Modula II and III, Eiffel, and Go that put the name of the variable before the type, such as:

var
    a : integer;
    b : integer;

So, at least in this respect, Kotlin's syntax is more like Pascal than C. While it's not what's the most popular at the moment, there's certainly a lot of precedent for it as well.

As to why you'd do it: one reason is that it's generally easier to parse (for both people and compilers, at least in my experience).

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