Feature Request: Remove Curly Brackets

Hey Coders,

we all know the neverending discussion about the following examples:

fun getName() {
  return name
}

and

fun getName()
{
  return name
}

Putting the opening curly bracket in the same line or not. I personally like the second way. When you write more code, the first way tend to get messy. But official style-guides use the first way alot, so you kinda have to stick with that.

Other Languages, like ruby or python, don’t have curly brackets. If you are not used to it, you need a little bit of time to adapt to it. But I bet you will like it. Because the code looks so much cleaner without all the curly brackets. Especially when you write nested code.

So I was wondering what would it look like, if Kotlin would not have the curly brackets too. Lets say we remove the opening bracket and replace the closing bracket with the keyword ‘end’ (just like in ruby). Like this:

fun getName()
  return name
end

Doesn’t look that much improved, right? But what if we have something a little bit more complex, for example creating an Overservable:

Observable
  .just(1, 2, 3, 4, 5)
  .subscribe(object:Observer<Int>() {
    override fun onNext(data: Int) {
      // todo
    }

    override fun onComplete() {
      // todo
    }

    override fun onError(throwable: Throwable) {
      // todo
    }
  })

And here without the curly brackets:

Observable
  .just(1, 2, 3, 4, 5)
  .subscribe(object:Observer<Int>()
    override fun onNext(data: Int)
      // todo
    end

    override fun onComplete()
      // todo
    end

    override fun onError(throwable: Throwable)
      // todo
    end
  end)

If we need the opening curly bracket as separator, like here:

Observable.create { emitter ->
  emitter.onNext(1)
  emitter.onComplete()
}

We could replace it with the keyword ‘do’:

Observable.create do emitter ->
  emitter.onNext(1)
  emitter.onComplete()
end

So, what do you think?

I think this is a question of preference the same as where to put the opening braces.
I personally don’t care either way as long as it is consistent with the language. The only version I don’t like is python with the indent defining the scope.

As for changing it. It is simply to late. Having both options would be confusing at best and this is a decision which had to be made in the early design phase of the language. Changing this now would create hundreds of problems without solving anything.

7 Likes

Thank you for your response. Yeah the python-indent-defining is not that smooth. The ruby-style ist definitely better.

I agree with you, that it is not the right thing to do, if it brings a lot problems by changing the style. But when not, this could be an optional thing and coders can use the style they want, without breaking the convention of the current project and the decision of the team. Can you provide some examples where you see problems can occur? Do you maybe think, that adjusting the kotlin-compiler to the other style would be a to complex adventure?

I just think this would be a massive change with no advantage. If you want it to be optional you need to support 2 completely different syntaxes throughout the compiler. You would need to add a whole lot more documentation think about all the edge cases like the one you pointed out and I am sure there will be more once you start looking.
I don’t know how much work this would be exactly but I don’t think it is worth it. I myself don’t know how the kotlin compiler works exactly but I can’t imagine this to be a trivial change.
Also what do you actually gain from it except for splitting the community.

Right, splitting the community is not a good thing. And maybe doing it as a optional thing is not good too, instead of just defining how to use it. But the risk is, that a lot of people will not agree with that, because they used to do it the way with the brackets. But I always thought people want to go further and improve languages or create new ones. Thats why Kotlin was created. It feels like people wanna get rid of the brackets because of the placing of the opening bracket on same line and the ongoing discussion about the style. And I’m wondering why there no changes. For me code-style is important, and when you have good readable code you feel comfortable. And removing the curly bracket is good alternative way to get much cleaner code, without destroying important paradigm.

Maybe I missed something but I think that conclusion is wrong. Yes there is a discussion about where to put the opening brace but that does not mean that the conclusion is to remove them completely. That’s like saying I don’t know which football team is better so let’s just remove all competition.

I don’t think this is true. I mean in what way is your example cleaner with end than with braces?

1 Like

I think the examples with end are too simplistic because you left out return values for the functions which makes the distinction between the return type and start of the body harder to find.

I think the root of the whole problem is the unsupportable and totally ridiculous notion that hiding the opening brace at the end of the line is a good idea. With the opening brace on its own line it is much more readable.

And unfortunately I work at a place that for some reason follows this unreadable practice.

And the fact that someone like Sun with Java promoted this style should bear no weight at all. Always seek the style that is most readable.

1 Like

I have to disagree. The style choice doesn’t matter. Braces are better than do-end

Rant about braces style:

I find code much easier to read when the brace is on the same line–hear me out because this was not my opinion before I started using Kotlin.

I used to think there it was all preference, and I used to strictly prefer the opening brace on its own line. When I started coding in Kotlin I quickly found myself switching to the same-line style. It appeared cleaner when coding in Kotlin. For Java, I continued to use next-line awhile until I finally had to admit I had become a filthy same-liner and no longer preferred next-line.

It’s not just preference. Trailing closures mix beautifully with the same-line style:

fun doTheThing() = things.forEach {
    ... // Can't place that brace here.
}

My office uses Groovy and mostly the next-line style. For Groovy (like Kotlin), it sure makes things less readable, but the effect of style is so negligible (when not using trailing closures), I’d gladly support next-line over inconsistency. Either style is more readable than both.

About the proposed do-end:

My point is, the root of the problem is not the same-line/next-line style.

Here’s what I gather the main premise is:

This is not true. Braces are easily understood by even those new to programming. They clearly sign post a block of code like a magazine quote.

As for do and end:

  • They’re English specific (which isn’t really a problem).
  • The do hides more within the other characters (code highlighting could help with that).
  • The do would clash with the current do keyword in do-while loops.
  • The start of a block would be implicit without the do (and possibly confusing to read at a glance).
  • DSL’s would be distinctly less readable.
  • One-liners would be distinctly less readable:
list.map do it.readValue() end.filter do it.validateWithin(context) end

Still, in all the ways I can think of, the proposed alternatives of do and end are either just as readable as braces or less readable than braces.

Yes, code with lots of nesting can get confusing. There are some things you can do to improve the readability–I would recommend using the same-line style (although next/same line style has a negligible effect if you’re avoiding trailing closures)–but removing braces in place of do and end won’t solve the readability problem and could make it worse.

3 Likes

I find braces easier to understand (vs. any word like “end”) as it wraps / encloses the block of code so to speak. I used Visual Basic way back in high-school so I remember transitioning to braces in University produced way less clutter (I could focus on the important bits more).

I used to prefer braces on separate lines when I was in University. I switched over to prefer keeping them on the same line after dealing with larger code-bases as it avoids excessive scrolling. It actually makes the code easier to understand since I can see more of it on screen at a time.

Example:

if (person.isHappy())
{
    greet(person)
}
else if (person.age > 20)
{
    promote(person)
}

vs.

if (person.isHappy()) {
    greet(person)
} else if (person.age > 20) {
    promote(person)
}
1 Like

Almost forgot, there’s this post that could help with nesting situations: Function name hints at lambda's closing braces

I Like the participation to this topic.

@Wasabi375 It just doesn’t look that much overloaded, like the one with braces.

@dalewking I really forgot an example with a return type. Well noticed. Ok, maybe it would look like this:

fun getName(): String?
  return name
end 

I dont think this is hard to understand or hard to read. For really simple functions, that doesnt look that much improved. Its more a thing for more complex code.

Would be awesome if that always would be possible. But please dont forget, most of the time you are not working alone on a project - the decision of the team is important - and you kinda have to follow the official style-guides.

@arocnies I agree, that ‘do’ can be confused with do-while loops. But the compiler could be smart enough to differentiate between starting a block or do-while loop. Or just use another word instead of ‘do’ for blocks. And while speaking of do-while, lets bring an example:

do
  // todo
while (i != null)

Looks smoother than this:

do {
  // todo
} while (i != null)

Anyway I agree with your one-liner-example, thats not that easy to read. (Maybe because the ‘end’-keyword is not highlighted like the ‘do’-keyword)

Thank you for the link. But honestly the example-code with hints doesn’t look better to me. The code is still complex and plus there are alot of extra hints. It can be more confusing.

@determinant Yeah thats the thing, every coder is different. I like the next-line-style better. Sure, the one-line-style is more compact, but can be alot more messy.

Let me just remind you that introducing the end syntax at this point, even without removing the current syntax, would be a breaking change. end is currently a valid identifier (and I would imagine that it is used quite a lot). Introducing any change that removes a valid identifier and makes it a keyword is a breaking change.

2 Likes

Thank you for your response, but you are missing the point of this topic. Its not specifically about the wording, its about the concept. When keywords are already in use, new ones can be introduced. Furthermore, I’m not a Kotlin-pro and I couldn’t investigate, that there is already an ‘end’-keyword in Kotlin. Can provide me some examples where the ‘end’-keyword is used?

The word end isn’t a keyword in Kotlin but it is a valid identifier so you can name variables and functions “end”.

I think this is a fun conceptual topic as well–despite the unlikelihood of such a massive change happening in Kotlin. :smiley:

There are some issues with using keywords like end instead of braces that make languages like Python very difficult to understand when it comes to lambdas and higher-order functions. Here’s an excerpt from a Python tutorial on composing functions with lambdas in Python:

Some programmers find that using unnamed functions from lambda expressions to be shorter and more direct. However, compound lambda expressions are notoriously illegible, despite their brevity. The following definition is correct, but many programmers have trouble understanding it quickly.

Idiomatic Kotlin code heavily uses lambdas to make things clear and concise. Kotlin’s extension functions and extension lambdas make DSL’s and builders easy and readable. Both of these features would be worse without braces. Here’s an example from Kotlinx.html converting the braces to ends (do was left out where possible):

window.setInterval( do
    val myDiv = document.create.div("panel")
        p do
            +"Here is "
            a("http://kotlinlang.org") do +"official Kotlin site" end
        end
    end

    document.getElementById("container")!!.appendChild(myDiv)

    document.getElementById("container")!!.append()
        div do
            +"added it"
        end
    end
end, 1000L)

and here’s the original:

window.setInterval({
    val myDiv = document.create.div("panel") {
        p { 
            +"Here is "
            a("http://kotlinlang.org") { +"official Kotlin site" } 
        }
    }

    document.getElementById("container")!!.appendChild(myDiv)

    document.getElementById("container")!!.append {
        div {
            +"added it"
        }
    }
}, 1000L)

Another aspect of Kotlin code that would be heavily affected is chained trailing closures. For example, working with sequences or streams:

val result = listOf(1, 2, 3, 4, 5) 
  .map { n -> n * n } 
  .filter { n -> n < 10 }
  .first()

would become:

val result = listOf(1, 2, 3, 4, 5) 
  .map do n -> n * n end
  .filter do n -> n < 10 end
  .first()

Lambdas are heavily used in Kotlin for even things as simple as assertTrue { ... } (see the method here).

Languages like Python suffer greatly in readability when it comes to nested code and lambdas. Kotlin benefits from having braces as they are not only clearer than do-end but also more practical in functionality.

6 Likes

I think ruby is better readable than python. And ruby has no braces too. So its not always adequate to use python as an example. I think the first example you showed you can improve a little bit more:

window.setInterval( do
    val myDiv = document.create.div("panel")
        p
            +"Here is "
            a("http://kotlinlang.org") do +"official Kotlin site" end
        end
    end

    document.getElementById("container")!!.appendChild(myDiv)

    document.getElementById("container")!!.append()
        div
            +"added it"
        end
    end
end, 1000L)

I see, that removing the curly braces wouldn’t solve everything (e.g. for one-liner), but when it comes to classes or functions, it can improve the code and avoid the overload.

I see your point. The braces could give bit of an overwhelming feeling when glancing at it. Personally I get that same overwhelming feeling when my eye’s aren’t able to quickly find the start and end of a block of code.

For me, do-end is more pleasing to the eye aesthetically in simple cases. Your original examples demonstrate this well.

Still, despite end feeling more pleasing on first glance of simple cases, I think it’s less clear when trying to understand exactly what the code is doing.

I’ll have to look more at Ruby, and there might be other languages that address code blocks in interesting ways.

For languages like Groovy and Kotlin, braces function very well for using with lambdas, trailing closures, and higher order functions.
Python works well without braces and does so with white-space based code blocks, limiting lambdas to a single expression, and tuples.

The main reason I would be against this change for a language that already uses braces is that:

  • Braces work as they are now.
  • do-end doesn’t add any new functionality
  • do-end introduces more clutter when using lambdas
  • do-end introduces implicit starts of code blocks when leaving out the do
  • Braces are more aesthetically pleasing than do-end for chained trailing closures.
  • The minus 100 points rule

And some reasons to make the change for a language already using braces:

  • do-end is more aesthetically pleasing than braces when not chaining trailing closures.
  • The beginning brace/do could be implied in some cases and an end is more desirable than a single }

I’m with you. There are situations where the braces seem to be needless (instead the code is just pure and simple). And other situations would be more confusing by changing the style. Its not my intention to have a style-change and lot of things are getting worse, just because a couple things are getting well. The style-change should have an overall good impact to the code. I hope languages will be enhanced constantly, so developers can write good readable code. Because code-style is important. After all you face it every day and you have to feel comfortable with it. I know, that just changing a language would be a no-go. Because most people would not agree. This is why its not easy to please everybody. Language-designer want to have their syntax as mainstream as possible, so alot of people will use it.

1 Like

If you don’t like braces, you could always push them to beyond the right-hand edge of your screen to make your code look as if it uses Python-like indentation:

Observable
  .just(1, 2, 3, 4, 5)
  .subscribe(object:Observer<Int>()                                                  {
    override fun onNext(data: Int)                                                   {
      // todo
                                                                                     }

    override fun onComplete()                                                        {
      // todo
                                                                                     }

    override fun onError(throwable: Throwable)                                       {
      // todo
                                                                                     }}
)

Err, oh yeah… the obligatory winkie: :wink:

3 Likes

Nice one :smiley:

More serious idea: write an IDE plugin that hides the braces for you.

1 Like

@klitosk Damn, this is funny. Didn’t expect that :smiley:

@fatjoe79 I thought about something like that too. A plugin, that supports individual code-style. But I think this is not easy to do. Because you have to parse the code between the way it is stored and the way it should be displayed to the developer. But I like the idea.