Элвис, где альтернатива - это последовательность выражений? - PullRequest
1 голос
/ 27 мая 2020

Мне нужно проверить, присутствует ли значение на карте, и если его нет, сделать что-нибудь еще и вернуть.

По причинам, выходящим за рамки этого фрагмента кода, мне нужно сделать это без проявления null в качестве значения переменной , то есть без какой-либо из переменных, имеющих тип, допускающий значение null.

Это то, что у меня есть до сих пор:

fun matchVariable(x: Variable, y: Term, m: MutableMap<Variable, Term>): Boolean {
    if (typeOf(x) != typeOf(y)) return false
    val x1 = m[x]?:{
        m[x] = y
        return true
    }
    return x1 == y
}

The ' return true 'получает сообщение об ошибке, что return здесь не разрешен, поэтому кажется, что значение по умолчанию для оператора Элвиса не может быть блоком из нескольких выражений.

Я мог бы выделить эти две строки в отдельную функцию; это запасное решение.

Но похоже, что должен быть краткий способ сделать это в строке (при соблюдении вышеуказанного критерия не проявлять null как значение переменной). Есть?

Ответы [ 2 ]

3 голосов
/ 28 мая 2020
Изменяемая карта

Kotlin имеет встроенную функцию getOrPut для этого варианта использования.

fun matchVariable(x: Variable, y: Term, m: MutableMap<Variable, Term>): Boolean             
{
    if (typeOf(x) != typeOf(y)) return false
    return m.getOrPut(x) { y } == y
}

Тот же код с объяснением / комментариями.

fun matchVariable(x: Variable, y: Term, m: MutableMap<Variable, Term>): Boolean {
    if (typeOf(x) != typeOf(y)) return false

    // if m[x] exists, it will be returned by `getOrPut`
    // else m[x] will be set to y and y will be returned by `getOrPut`
    return m.getOrPut(x) {
        // you can do some operations here.
        print("Updating m[$x] = $y")

        // last line will be value to be 'put' in map and same value will be returned.
        y
    } == y // value returned by `getOrPut` compared with `y`
}
2 голосов
/ 28 мая 2020

В Kotlin (и в отличие от Java) пустой блок { } является лямбда, и вы не можете использовать оператор return в лямбде, если он не является аргументом встроенной функции высшего порядка.

В случаях, когда вы хотите использовать организационные скобки, как в Java, вы можете использовать функцию run без области действия. Он выглядит так же, как и у вас, но с run перед скобами. Поскольку run является встроенной функцией более высокого порядка, вы можете использовать в ней return.

fun matchVariable(x: Variable, y: Term, m: MutableMap<Variable, Term>): Boolean {
    if (typeOf(x) != typeOf(y)) return false
    val x1 = m[x]?: run {
        m[x] = y
        return true
    }
    return x1 == y
}

В качестве альтернативы, функция области видимости also может использоваться для краткого выполнения некоторого побочного эффекта перед возвратом чего-либо :

fun matchVariable(x: Variable, y: Term, m: MutableMap<Variable, Term>): Boolean {
    if (typeOf(x) != typeOf(y)) return false
    val x1 = m[x] ?: return true.also { m[x] = y }
    return x1 == y
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...