Why are there THREE ways to declare a function? Unify?


#1

There are (at least?) three way to declare a function in Kotlin:

fun java(num: Int) {   println("Number is $num") }

val literal = fun(num: Int) {   println("literal is $num") }

val coffeescript = { (num: Int) ->   println("Too many functions! $num") }

Is there a benefit to having all these different ways to declare functions? JavaScript has these three styles as well, but CoffeeScript simplified that and only allowed the last one, which works perfectly. Or does each of these styles have different advantages/disadvantages? When to use which? How are they different?

With “:=” it could look like this:

something := fun(num: Int) {

  println("Looks okay?")

}

…and if you replaced braces with indentation it could look like this:

coffeescript := (num: Int) ->   println("This uses Go's := and significant whitespace.")

For block-parameters, you could still distinguish blocks from statements by where you put the closing parethesis:

theThirdParameterIsABlock(1,2)

  if(it.isFine)

          doSomethingWith(it)

  else

          complainAbout(it)

theThirdParameterIsEitherWhatFOrWhatGReturned(1,2,

  if(it.isFine) // "it" must be declared already.

          f(it)

  else

          g(it)

)

(I’m not entirely sure about that last part though)


#2

We need at least two functions. A "normal" function with its own scope and a closure or lambda function, that allows variables to be used from the outer scope. IDEA explicitely underlines variables, when they are used inside of a closure. A reason for the use of two different function types is (I think) to have a safety net and to minimize side-effects. Another reason is that Java 8 provides specific optimazion for lambda function (I think).

Some words to CoffeeScript: I like the language, I used a decent (LiveScript) of it for a while and found it very expressive. LiveScript also get rid of some nasty syntax issues of CoffeeScript. A problem with CoffeeScript (and LiveScript) is, that the syntax is ambigues in some cases.


#3

There is one way to declare a function, and it's the first syntax you have shown. Only the functions declared using that syntax become methods of classes, can be overridden, etc.

The choice between the three syntaxes exists only when you’re declaring named local functions. Doing so is a relatively rare occurrence in Kotlin, compared to the other contexts where functions are defined. In that particular syntax, the recommended syntax is still the first one, because it’s consistent with other function declaration contexts. The other two syntaxes work, because they folllow from how the Kotlin syntax works, and it’s not clear why or how we could come up with a rule to forbid that.