Kotlin design/syntax: lambda, string templates

Two questions.

  1. Someone knows why lambdas / “arrow functions” look like this?
    type: (para: Int) -> Int
    body: {para: Int -> para + 10}

why not also (para: Int) -> {para + 10} for the body part? Like in typescript
Is there a practical reason? For me it feels pretty inconsistent

  1. String templates
    Why the decision was to take $ for string templates and not the (in my opinion more modern) {{variable}} syntax used in the mustache templating system.
    Would it be possible to use both or to extend kotlin that I can use it?
  1. It is useful to add it parameter as default. E.g. code blocks below are equivalent:
{ it -> it + 1}
{ it +1}

So as you can see, arrow is optional.

  1. I prefer adding only one symbol in general case, e.g. using $ before variable, or &, etc. However I don’t know exact answer here.
1 Like

About your second question. I don’t think there is a “more modern” version out there. As far as I can tell nearly all programming language uses a different system for that.
Compare C# $ - string interpolation - C# reference | Microsoft Docs

string message = $"someExpression = {someExpression}"

swift Strings and Characters — The Swift Programming Language (Swift 5.7)

let message = "someExpression = \(someExpression)"

js template literals Template literals (Template strings) - JavaScript | MDN

const message = `someExpression ${someExpression}`

python 6.1. string — Common string operations — Python 3.4.10 documentation

message = Template('message $result').substitute(result=someExpression)

and your example of the mustache templating system. There are probably more systems out there for this, but using the same system as java script and a similar one to python and C# seems smart. Lot’s of people are probably already familiar and as @imanushin pointed out it just requires one extra character (that isn’t widely used in strings).
That said kotlins development started in 2011 I think and this js feature is part of ES2015 so it appeared 4 years later. I don’t know how long string templates have been around before the 1.0 kotlin release but there is a good chance it was out before this js feature. Same goes for the C# templating, which is part of C# 6 (also 2015) and swift was released in 2014 so also after this feature was part of kotlin. I can’t really tell when python introduced this, but in python it’s a library and not a language feature anyways.
From what I can tell kotlin is one of the “modern” programming languages that first introduced this as a language feature. Obviously they didn’t invent the idea but I can’t find anything else that has this as a language feature, though this exists as a library for nearly all languages.

TL;DR I don’t really know why kotlin chose to use $ for this, but from what I can tell it’s the one most used for this and only a single character. Kotlin also seems to be a pioner in adding this as a language featuer providing additional type saftey so there wasn’t a “modern” way to do this before that kotlin could just follow.

I don’t actually use most of the languages listed abvoe so please don’t kill me if I made any syntax mistakes in the small samples :wink:

2 Likes

To you first question: In many cases a function consists of more than one expression and then you would need curly braces anyway. It would look like this:

(para: Int) -> {
   some
   more
   expressions
}

That is essentially the TypeScript syntax.
Ingredients: (){}

The Kotlin syntax doesn’t need additional syntax if more than one expression is in the function body:

{ para: Int -> 
   some
   more
   expressions
}

Ingredients: {}

The -> sign does already separate arguments from the body, so there is no need for additional syntax elements. I find this quite elegant!

First I wanna thank all of you for answering :slight_smile:

Yes of course but you also could do it like this way

(it) -> {it + 1}
{it + 1}

So as you can see, arrow is optional ^^

When invoking a function that takes a lambda, you can omit the function’s parantheses. For example:

list.fold { acc, v -> acc + v }.also { print(it) }

This would not look so nice with your proposed lambda syntax.

@Wasabi375
The idea might be from PHP…
I prefer to write a bit more… and get rid of ${} also it’s not much effort to write {{}}

Thank you for your listing…
Modern maybe only for me, but yes I would really prefer {{}}

@medium
Sure but () was always something for me to do something special, like truth check or passing parameters and {} for just “normal” program code. From that point of view it looks weird to me… probably I am the only one with this feelings^^

@fatjoe79
list.fold { acc, v -> acc + v }.also { print(it) }
list.fold (acc, v) -> { acc + v }.also { print(it) }
hmm maybe but it doesn’t look so bad to me its easier to distinguish between head and body but maybe I only have to get used to…

To me that looks as if fold is invoked with 2 parameters acc and v.

1 Like

Oh yes actually obvious… :sweat_smile:
That seems to be the reason.

Thank you

One of Kotlin’s best features is how you can use higher order functions to implement control structures. See, for example, uses of launch, async, withContext, let, etc. etc. It’s the brace syntax for lambdas, along with support for inline functions and the special syntax for trailing lambda parameters, that makes it possible to do this so naturally.

I don’t now for certain either, but one thing I can observe is that the syntax used is almost identical to the syntax used by the sh (and by extension bash) shell script languages.

At the end of the day, the syntax used doesn’t really matter all that much anyway, as long as it allows enough input. Certainly “modern” isn’t necessarily better.

The {} syntax makes it a lot more convenient to write DSLs.

Right now you can write this:

repeat(6) {
  println(it)
}

It allows developers to create functions that look like keywords (especially with inline lambdas). You’ll see that Gradle is pretty much 100% this, as well as the HTML DSL, etc.

If it was written like Typescript, you’d have to write:

repeat(6, (it) -> {
  println(it)
})

That’s a lot of boilerplate for not a lot of meaning, and it doesn’t take that long to get accustomed to :slight_smile:

That’s what powers a lot of the nice stuff about Kotlin: functions like run, with, apply, the whole sequence API, most of the coroutines API…