Assignments as expressions

Is there a discussion or rational to forbidding using an assignment as an expression in Kotlin?

I love the ability Kotin gives me write terse code, but this goes kind of contrary to that.

I understand the risks, but some countermeasure can be taken, like GCC that warns if you do if (x = 3) (in kotlin, only boolean variable would affected so if (x = true)).

Maybe this impacts smart casts?

There’s a discussion here, but I’m not really convinced – the cases mentioned in Micah’s last post seem quite frequent to me.

Simple recent example:

class Dechain<T> (var head: Chain<T>? = null, var tail: Chain<T>? = null)

    ...

    override fun pushFront(e: T)
        = if (head == null) {
            head = Chain(e, null, null)
            tail = head
        } else {
            head ?. prev = Chain(e, null, head)
            head = head ?. prev
        }

    // what I really wanted to write:
    override fun pushFront(e: T)
        = if (head == null) head = tail = Chain(e, null, null)
          else head = head ?. prev = Chain(e, null, head)

    ...

I’d even take a weird syntax (or less weird like :=) or even something that triggers warnings.

Edit: closest I can get, but not near as readable:

fun pushFront(e: T)
    = if (head == null) Chain(e, null, null).let { head = it ; tail = it }
      else Chain(e, null, head).let { head ?. prev = it ; head = it }
1 Like

Not going into philosophy of it, simple technical answer: the syntax for named arguments: foo(a = b) means “call foo with the parameter a having value b”.

2 Likes

Wrote this reply before noticing that this thread is nearly 10 years old

On the philosophy side of it, Kotlin favors functional programming not imperative programming, which means mutable state is not something it is going to favor. But of course a doubly-linked list like this is not something that is a good fit for functional programming.

Any way I might implement your method like this, which is a heck of a lot more readable than your version:

    override fun pushFront(e: T) =
        Chain(e, null, head).let {
            head?.prev = it 
            tail = tail ?: it
            head = it
        }
2 Likes