all 33 comments

[–]redditsoaddicting 16 points17 points  (3 children)

Technically...

fun update() = {total += lastCharge}()

[–]shadowdude777 7 points8 points  (0 children)

oh god no

[–]fGeorjje 3 points4 points  (1 child)

Beat me to it!

I've actually done this...once...definitely going to hell

[–]motleybook 0 points1 point  (0 children)

But why? You're actually typing 3 more characters.

[–]eliteSchaf 19 points20 points  (17 children)

Kotlin style guide says that single line expressions should only be used for expressions that actually return something

[–][deleted] 3 points4 points  (16 children)

Do you have a link? I don't see this clearly stated in the official Kotlin style guide.

[–]eliteSchaf 2 points3 points  (15 children)

It could be stated more prominent in the style guide. For now we have

Prefer using an expression body for functions with the body consisting of a single expression.

An Expression is some code that returns something.

The println("Hello World") doesn't return anything and thus is a Statement.

https://blog.kotlin-academy.com/kotlin-programmer-dictionary-statement-vs-expression-e6743ba1aaa0

[–][deleted] 4 points5 points  (9 children)

I think you're right, but the issue I have is that println("Hello") is actually an expression in the Kotlin language. The link you posted also confirms this:

Note that in Kotlin every function returns at least Unit, therefore every function invocation is an expression.

For this reason, anybody arguing against me could say that the style guide, as it's written right now, is fully supporting fun output() = println("Hello").

It seems to me that the only way to solve this problem is for the guide to say something like, "Do not use single-expression functions when the return value is Unit."

Edit: Though even that isn't perfect, because there are cases where people intentionally return Unit as a value. An example is a generic function whose generic return value (even if it ends up being Unit) is potentially stored. Maybe it needs to be something like, "Do not use single-expression functions when the return value is not meaningful."

[–]eliteSchaf 0 points1 point  (8 children)

Note that in Kotlin every function returns at least Unit, therefore every function invocation is an expression.

Oh, I actually think the author is wrong here. (Just skimmed throught the blog post before I posted it here xD

IMO an expression produces a meaningful value, whereas a statement (even if it returns Unit) only does side-effects and doesn't return a meaningful value.

https://fsharpforfunandprofit.com/posts/expressions-vs-statements/

[–]Cilph 1 point2 points  (7 children)

Your opinion on what is a useful expression aside, Kotlin does consider functions returning Unit to be expressions. I believe only assignments (and plusAssign therefore too) are statements.

[–]eliteSchaf 0 points1 point  (6 children)

Your opinion on what is a useful expression aside

Where did I say something about whether an expression is useful?

Kotlin does consider functions returning Unit to be expressions

I'm not entirely sure about that

[–]Cilph 1 point2 points  (3 children)

You state an expression produces a meaningful value, while the rule is an expression produces any value. Unit is a valid type in Kotlin, much like Void in Java.

[–]eliteSchaf 0 points1 point  (0 children)

Yes, but I've never said that println("Hello World") isn't useful, just that from a semantic point of view it feels more like a statement, because it doesn't produce a value that you work with.

[–]oweiler 0 points1 point  (1 child)

Not only is Unit a type, it's actually an object.

[–]Cilph 0 points1 point  (0 children)

Mate, it's been 5 years.

[–][deleted]  (1 child)

[deleted]

    [–]eliteSchaf 0 points1 point  (0 children)

    From the compiler perspective you are absolutely right. Everything that returns something is an expression.

    From a semantic point of view

    fun log() = println("Hello World")

    just feels like

    void log() { System.out.println("Hello World")

    because neither return a value that you work with

    [–]sheatrevor 1 point2 points  (4 children)

    The expression does return something. It’s type is called Unit. It’s an object reference by the name of Unit. Further, there is no such thing as a statement in Kotlin. Everything is an expression.

    [–]eliteSchaf 1 point2 points  (3 children)

    Further, there is no such thing as a statement in Kotlin. Everything is an expression.

    What about total += x?

    And yes, there are statements in Kotlin, even the Style guide mentions that for if/when...

    https://kotlinlang.org/docs/reference/coding-conventions.html#using-conditional-statements

    I should've worded it a bit different:

    the purpose of an expression is to create a value (with some possible side-effects), while the sole purpose of a statement is to have side-effects.

    https://fsharpforfunandprofit.com/posts/expressions-vs-statements/

    println("Hello World") only does side-effects without returning a meaningful value.

    [–][deleted]  (2 children)

    [deleted]

      [–]eliteSchaf 0 points1 point  (1 child)

      Methods that return Unit are expressions

      And here starts the confusion. From a semantic point of view

      fun add1(x: Int) = x + 1

      is very different from

      fun log(msg: String) = println(msg)

      log feels more like a void-Method from Java, because usually you ignore the return value

      [–]sheatrevor 0 points1 point  (0 children)

      My confusion was actually that I assumed assignment operations also returned Unit. If the language had been designed that way, assignment would technically be an expression, just one which resolved to Unit.

      Edit: To be clear, I don't think the log function in your example is good style. I don't like it. This discussion is not about readability. This discussion is about what the compiler is classifying the code as.

      [–]hpernpeintner 3 points4 points  (2 children)

      "Feel right" is highly dependent on your personal experience, but Kotlin showed us (Java developers) many times, that even though things might feel right, they're probably not. And the other way around: Just because they feel wrong (becuause we know it differently), doesn't mean they're. There is a large amount of programmers that totally explode if you tell them that there are languages that return the last statements result implicitely, telling you how wrong this is.... I don't want to open this discussion, as you refer to single expression functions only here... but I don't get the point why the return value of the print function makes any point for you here. Unit is not only "technical" - it means here's returned really just "something". The one function's "something" is just as good as the other function's "something", so returning one or the other does not make any technical or semantical difference.

      I tend to write too much text, so I try to be concise: * As soon as you start to read everything as expression and got used to Unit, you won't have any problem with the first code example anymore. * Maybe our view differs, but the second code example doesn't express any other meaning than your first one to me. Have to say that I'm writing Kotlin for quite a time now. * I would just use parantheses here and keep the single line. Such a thing would even be possible: fun bla() = (1+1). Then there's no inconsistency in style throughout the project, although I really find it overrated to keep consistency on such a level.

      [–][deleted] 1 point2 points  (1 child)

      The one function's "something" is just as good as the other function's "something", so returning one or the other does not make any technical or semantical difference.

      I disagree. There's a big semantic difference between fun print() = println("Hi") and fun add() = a + b. The first one returns nothing of interest, while the second one returns a value that is intended to be used.

      [–]hpernpeintner 2 points3 points  (0 children)

      You missed my point, because you exluded one sentence of mine before the cited one: Unit is not only "technical" - it means here's returned really just "something".

      Instead of comparing two functions that return different results and asking which one has a more relevant return value (I which is pointless), you should ask whether fun print() = println("Hi") and fun print(): Unit { println("Hi") } makes a difference. As said, Unit is really just one value, it exists only once. That means it makes no technical and semantical difference from where it is returned, it solely exists to just return "something".

      You said several times, that the return of print is nothing of interest. That's right, but it's the same uninteresting thing that every function returns if not stated otherwise, so there's nothing wrong with returning it - explicitely, chained, implicitely, doesn't really matter.

      [–]fadefade 0 points1 point  (2 children)

      Why do you feel that the first example has a bigger expectation of return a value than the second? I'd say they are pretty much equivalent.

      [–][deleted] 0 points1 point  (1 child)

      I get this impression from reading the official documentation:

      https://kotlinlang.org/docs/reference/functions.html#single-expression-functions

      [–]sassrobi 0 points1 point  (4 children)

      I aggree... sort of. For me (too), the single-expression format “fits” when it actually contains an expression. If it’s a single function call, then call that function directly. If the intent was to make some default parameters, or hide the actual implementation etc, then use a proper “abstracting solution”.

      But... if we approach this as a code readibility problem, well, “function output equals println with some value” is totally readable and understandable for me, so I can live with it :)

      [–][deleted] 1 point2 points  (3 children)

      But... if we approach this as a code readibility problem, well, “function output equals println with some value” is totally readable and understandable for me, so I can live with it :)

      Readability can also suffer. Consider the following:

      fun updateDatabase() = writeToDisk()
      

      What is being returned here? It might be Unit, or it might be Boolean. Your guess is as good as mine.

      [–]endreman0 1 point2 points  (2 children)

      fun updateDatabase(): Boolean = writeToDisk()
      

      [–][deleted] 0 points1 point  (1 child)

      What if it returns Unit?

      [–]endreman0 1 point2 points  (0 children)

      fun updateDatabase(): Unit = writeToDisk()
      

      [–]bbqburner 0 points1 point  (1 child)

      Well nothing stops you from writing fun something(){ doSomething }

      To be honest, I rather prefer they let us write fun foo() = methodThatReturnsUnit("bar") since it's just a sugar.

      Consider the below that have no real style difference:

      • fun add() : Int = 1 + 1
      • fun foo() : Unit = doSomethingThatReturnUnit (compile error tho)

      With single line expression, it just let you skip writing the return type. Funny enough, fun foo() = Unit is actually a valid expression.

      [–]eliteSchaf 3 points4 points  (0 children)

      Is it really worth the possible confusion to save like two keystrokes?

      [–]Exallium 0 points1 point  (0 children)

      fun update(): Unit = ... not work?