24

Is there a way to get the value of the expression I passed into the when statement?

In my application I have a KeyListener like that

_content.addKeyListener(object : KeyAdapter() {
    override fun keyPressed(e: KeyEvent?) = when(e?.keyCode) {
        KeyEvent.VK_T -> mainWindow.enterTrainingState()
        KeyEvent.VK_P -> mainWindow.enterPlayState()
        KeyEvent.VK_E -> mainWindow.close()
        else -> println(e?.keyCode)
    }
})

Has Kotlin a neat syntax to access e?.keyCode? I don't really want to repeat the expression.

1
  • I read the above comment and beginning of the accepted answer and conclude that it not possible but its a 'yes' since Kotlin 1.3. See the accepted answer, and read till the end! Commented Apr 29, 2021 at 9:00

4 Answers 4

49

Kotlin 1.3 has support for capturing the subject expression of a when in a variable. This is the syntax:

when(val keyCode = e?.keyCode) {
    KeyEvent.VK_T -> mainWindow.enterTrainingState()
    KeyEvent.VK_P -> mainWindow.enterPlayState()
    KeyEvent.VK_E -> mainWindow.close()
    else -> println(keyCode)
}

Original answer

I had this problem myself a couple of days ago. I think it would have been nice to be able to access the value as it inside the when-expression.

I solved it by assigning the expression to a val before the when expression:

val keyCode = e?.keyCode
when(keyCode) {
    KeyEvent.VK_T -> mainWindow.enterTrainingState()
    KeyEvent.VK_P -> mainWindow.enterPlayState()
    KeyEvent.VK_E -> mainWindow.close()
    else -> println(keyCode)
}

Unfortunately, this would require you to add extra braces and lines. The upside though, is that e?.keyCode would only be evaluated once. It may not matter in this exact case, but if the expression was bigger, this approach would be suitable.

Edit:

Another possibility it to wrap the when expression in a call to let. It lets you access the parameter with it. Like this:

e?.keyCode.let {
    when(it) {
        KeyEvent.VK_T -> mainWindow.enterTrainingState()
        KeyEvent.VK_P -> mainWindow.enterPlayState()
        KeyEvent.VK_E -> mainWindow.close()
        else -> println(it)
  }
}
Sign up to request clarification or add additional context in comments.

7 Comments

Which, in this case, will turn the OP’s expression into a block, thus requiring extra braces and lines.
Accessing it via it was my first idea too... but sadly it is not possible (would be cool if it was possible). And as Michael already mentioned your solution converts my expression into a block.
@MichaelPiefel Yes, that is why I said it would be nice if we could access it with it. This possibility has one purpose, which is that e?.keyCode would only be evaluated once. It may not make a difference in this case, but if it was a bigger expression, I would say this is the way to go.
@Exhauzt See my edit and see if you find that to be better.
@Exhauzt I wonder what made this answer so much better than mine…
|
5

It's not possible as of Kotlin 1.1. There is an open feature request for this functionality: https://youtrack.jetbrains.com/issue/KT-4895

Comments

4

You may try the following, even if it changes the semantics slightly. In your case it may well be OK, I guess.

_content.addKeyListener(object : KeyAdapter() {
    override fun keyPressed(e: KeyEvent?) = e?.keyCode.let {
        when(it) {
            KeyEvent.VK_T -> mainWindow.enterTrainingState()
            KeyEvent.VK_P -> mainWindow.enterPlayState()
            KeyEvent.VK_E -> mainWindow.close()
            else -> println(it)
        }
    }
})

Comments

2

With Kotlin 1.3, you can set the parameter as a scoped variable and access it.

_content.addKeyListener(object : KeyAdapter() {
    override fun keyPressed(e: KeyEvent?) = when(val keycode = e?.keyCode) {
        KeyEvent.VK_T -> mainWindow.enterTrainingState()
        KeyEvent.VK_P -> mainWindow.enterPlayState()
        KeyEvent.VK_E -> mainWindow.close()
        else -> println(keycode)
    }
})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.