Why are assignments not expression in Kotlin? Is t...
# announcements
a
Why are assignments not expression in Kotlin? Is there a limitation, or it is intended to not be an expression?
n
interestingly i was recently going through python's recent assignment expressions (walrus operator) that was merged, seeing how the use cases would look like in kotlin. most can be made elegant but there are a few that look awkward still.
v
I have no idea, but I have two guesses. In Java a typical typo is to forget one
=
in an
if
like
if (x = 1)
where it should have been
if (x == 1)
. This can easily lead to bugs and can be prevented with assignments not being expressions. The second guess is, that for
method(x = 1)
it would be ambiguous whether you want to assign 1 to x and give 1 as first parameter, or whether you want to set the parameter x to 1.
👍 2
a
The intellij's automatic Java -> Kotlin converter converts
(a = b) != c
to
b.also { a = it } != c
Which is kotlinic, but not so readable.
I also like the way Python's
:=
operator is implemented, I used them and this question ticked in my mind!
n
i have kidna mixed feelings. honestly, most of the python use cases of := have much better solutions in kotlin.
1
not all
the one I found hard to come up with a good solution for was in python you can do:
Copy code
if condition and (x := something):
    ...
and use
x
. And obviously you can do that for arbitrary combinations of conditionals
a
unfortunately Kotlin having strict type system, it won't be able to have that
Copy code
(x := something) != null
Or something is required to make it Boolean and fit inside if
Maybe something like this:
if ((x := b.toString()).isNotEmpty()) {}
n
Sure
there's no truthiness which also makes that hard
it's probably better just to have the extra nesting level
or add a helper function somewhere which returns
T?
based on
condition
and whatever boolean expression on
x
g
@Animesh Sahu could you show some real life code where you found you need this (converter is not always the best guideline, especially in such cases, because it tried to keep exact semantics of old Java code, which on practice is not always necessary
n
O(ne example in python was matching differetn patterns to regex
Copy code
if (x := pattern1.match(s)):
    ...
elif (x := pattern2.match(s)):
    ....
etc
I don't see any nice way to do this in kotlin without writing a tiny little DSL for it
g
@Nir i think its reasonable to say this is still an active area of kotlin language development. if
match
is a type-check then kotlin gives you this with
when
Copy code
when(val x = expression(s)){
  is Cow -> { } //x smart-cast to 'Cow'
}
But general pattern matching is still something all jvm languages --including java-- are wrestling with.
n
I'm not really sure how pattern matching solves thisproblem for you
even if you have pattern matching, you still have the same problem: you want each match to both assign/create a variable, and act as an expression
g
right sorry @Nir i was thinking about pattern matching in terms of type hierarchy and you of course mean pattern matching WRT Regexs
yeah the regex type is not elegant in kotlin
n
yeah, sorry, I didn't really make it clear
well, it's reasonably easy to make clear I think
you can do something like:
Copy code
regex_match(s) {
    pattern1 to {
        // use it
    },
    pattern2 to {
        use it
    },
}
etc
this is reasonably elegant but there is something to be said for just beinga ble to use the control structures naturally
handles unanticipated or unprovided use cases much better, etc
g
But isn't your example is more problem of pattern matching, not a problem of assignment to be expression?
n
Not really
The model in pattern matching is:.evaluate get an expression,.then try to match against that expression in different ways,.take the first successful one
This does additional work at each point
g
My point that without pattern matching or extending when it will not work anyway, so this example doesn't really relevant This case can be solves with a special syntax for when (how it now works for
when (val foo = exp())
but for whole block),, it doesn't require making assignment an expression
n
I don't really follow that at all, sorry
Are you saying the Kotlin equivalent doesn't work because Kotlin doesn't have truthiness?
Of course you can solve things with special cases, that's a given, the question is whether something is compelling enough to generalize
Special cases also have their own downsides
At any rate you asked for examples of assignment expression being useful, I provided one. The PEP has others, of varying relevance to Kotlin
g
Special cases also have their own downsides
This why important to see multiple real life cases when it required
a
How about:
Copy code
if (feature.isEnabled && System.getenv("test") != null) {

}
Somehow storing the result of getenv
g
use local variable
anyway, now write it with assignment expression
it was a discussion to introduce similar syntax to
when
assignment (in when with assignment proposal), looks that it in general under consideration But when it combined in
if
it doesn’t look very well, though, it of course has one advantage, it limits scope of this function So proposed something like
Copy code
if (val test = System.getenv("test"); test != null) {

}
a
It seems, the elvis operator can be better fit at this case,
Copy code
val test = System.getenv("test") ?: return
if (feature.isEnabled) {
}
g
but for me it not very convincing that extending scope of
test
local varaible is so much worse than messy code in if
yes, exactly
a
I'm still confused about this, I asked this just because it came to my mind :V don't take this seriously.
g
at least early return can solve many (but not all) similar cases
yeah, I believe the main rationale was as Björn said, to avoid common C-like languages bug related on usage of
=
instead of
==
😁 1
n
C++ now allows an initializer before the comparison
Similar to one of the suggestions above
The problem btw is not really the extra variable which I agree is minor
It's the nesting
Early return is nice of course but that's quite a large assumption that's not true in general that early return is ok
I will say it's not the end of the world and I don't think the case for assignment expressions is strong in Kotlin. I think these cases are mostly pretty isolated. Where they aren't isolated, like e.g. the regeex example, a little mini DSL is usually good
g
Yep, agree.