kotlin

How to translate code with assignment in conditional to Kotlin


I am trying to translate the following code from TypeScript:

if (coefficient == -1 && peekToken(/^\(/, tokens)) value = "1"
    else if (variable = getToken(/^[a-zA-Z]/, tokens)) value = variable;
    else if (number = getToken(/^(\d*\.\d+)|\d+/, tokens)) value = Number(0 + number);

to Kotlin:

    if (coefficient == -1 && peekToken(Regex("""^\("""), tokens) != null) value = "1"
    else if (variable = getToken(Regex("""^[a-zA-Z]"""), tokens) != null) value = variable
    else if (number = getToken(Regex("""^(\d*\.\d+)|\d+"""), tokens) != null) value = (0 + number).toDouble()

The first if conditional is fine. The second one shows an error: Assignments are not expressions, and only expressions are allowed in this context. Is there an idiomatic way of rewriting that line without turning the else-if into a block of multiple statements?


Solution

  • In your case the second line works like this:

    1. get result from getToken(Regex("""^[a-zA-Z]"""), tokens)
    2. check whether the result is not null (returns true false)
    3. assign the value to a variable (DOES NOT RETURN TRUE/FALSE)

    so basically, in your case kotlin does not know what to do, because there is an if statement that should contain a true/false, but it finds that you want to set a value to a variable there and it does not know what to do

    I'm guessing you've assumed kotlin would use take the variable value (that just got changed) and use it in the if check, but it won't

    One way to solve it would look like this:

    var value: Any? = null
    val variable = getToken(Regex("""^[a-zA-Z]"""), tokens)
    val number = if (variable != null) getToken(Regex("""^(\d*\.\d+)|\d+"""), tokens) else null
    
    if (coefficient == -1 && peekToken(Regex("""^\("""), tokens) != null) {
        value = "1"
    } else if (variable != null) {
        value = variable
    } else if (number != null) {
        value = (0 + number).toDouble()
    }
    

    or like this:

    var value: Any? = null
    
    val variable = getToken(Regex("""^[a-zA-Z]"""), tokens)
    val number = if (variable != null) getToken(Regex("""^(\d*\.\d+)|\d+"""), tokens) else null
    
    when {
        coefficient == -1 && peekToken(Regex("""^\("""), tokens) != null -> value = "1"
        variable != null -> value = variable
        number != null -> value = (0 + number).toDouble()
    }