Какой идиоматический способ Kotlin написать `if ... else null` как часть цепочек? ./ ?:? - PullRequest
1 голос
/ 01 мая 2019

(отредактировано для ясности)

Я продолжаю писать (if (x) f() else null) ?: (if (y) g() else null) ?: (if (z) h() else null) и тому подобное, и я уверен, что я не единственный ץ

Я всегда обращаюсь к функции, подобной valueIf, определенной ниже (которая равна takeIf с порядком обращения параметров, поэтому значение лениво), что позволило бы мне написать код, подобный getViewEventType2() вместо кода, подобного getViewEventType1() (оба уточняются ниже).

Есть ли идиома, по которой я скучаю?

(Кроме того, умеет ли компилятор работать с такими функциями или я должен бояться создавать слишком много временных замыканий?)

    private fun getViewEventType1(): String? {
        return if (intent.action == "android.intent.action.VIEW") {
            intent.data?.pathSegments?.let {
                if (it.size == 3 && it[0] == "app" && it[1] == "event") it[2]
                else null
            }
        } else null
    }

    private fun getViewEventType2(): String? {
        return valueIf(intent.action == "android.intent.action.VIEW") {
            intent.data?.pathSegments?.let {
                valueIf(it.size == 3 && it[0] == "app" && it[1] == "event") { it[2] }
            }
        }
    }

    inline fun <T> valueIf(condition: Boolean, func: () -> T?) =
            if (condition) func() else null

Ответы [ 2 ]

3 голосов
/ 01 мая 2019

Вы все еще можете использовать takeIf() для достижения того, что вы хотите, как показано здесь в функции расширения для Intent:

fun Intent.getViewEventType(): String? {
    return takeIf { it.action == "android.intent.action.VIEW" }
        ?.`data`
        ?.pathSegments
        ?.takeIf { it.size == 3 && it[0] == "app" && it[1] == "event" }
        ?.get(2)
}

Редактировать с помощью OP: это последний код, с которым я работал:

fun getViewEventType(): String? {
    return intent.takeIf { it.action == "android.intent.action.VIEW" }
            ?.`data`
            ?.pathSegments
            ?.takeIf { it.size == 3 && it[0] == "app" && it[1] == "event" }
            ?.get(2)
}
0 голосов
/ 01 мая 2019

Как показано в Wangs answer : takeIf - это путь для таких конструкций.

Я просто оставлю здесь все, кому интересно (как мой комментарий там уже применялся): вы можете опустить let в пользу безопасный оператор ?..Кроме того, вас также может заинтересовать уничтожение объявлений , что делает его немного более читабельным, на мой взгляд:

fun Intent.getViewEventType() : String? = takeIf { it.action == "android.intent.action.VIEW" }
        ?.`data`?.pathSegments
        ?.takeIf { it.size == 3 }
        ?.takeIf { (source, actionType) -> // destructuring in action... you may want to name the variables appropriately
            source == "app" && actionType == "event"
        }
        ?.get(2)

Я также использовал здесь функцию единственного выражения Но я оставляю это на ваше усмотрение.Поскольку вы здесь много цепочек, вы можете по крайней мере указать тип возвращаемого значения при использовании такой конструкции (которую вы также можете опустить).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...