Comments 24
В этом Kotlin похож на JavaScript. Как в JavaScript, в Kotlin можно достичь того состояния, когда вы уже не знаете, что такое this.
*что-то вычеркивает в записной книжке
Они есть во всех языках, но в некоторых для этого нужно сделать что-то невероятное.
А в Котлине, как показывает автор, на эти грабли можно будет наступить на каждом шагу :-(
Язык очень интересный, но складывается впечатление, что взяли все возможные фичи со всех языков и попытались все их уместить в один язык. В результате имеем такие вот забавные пазлеры.
«Неочевидная вещь» – это проблема дизайна, т.е. – «Долбанная ошибка дизайна».
Тут хорошо подойдет аналогия с UI/UX: все должно быть максимально просто и очевидно. Если это не так, значит есть проблема. Язык программирования – это товар, а Программист – потребитель/пользователь.
Если Вы не согласны с этим утверждением, тогда ответьте на вопрос: почему каждый год выходят десятки новых языков и почему каждый раз, когда крупная компания выпускает свой язык, то подымается хайп?
Kotlin, Scala, Groovy, TypeScript, Elm, CoffeScript, Rust, Go, Swift, etc.
На сколько помню, целью Котлина было облегчение разработки и защита от глупых ошибок. А в результате одни глупые ошибки заменили на другие.
«Неочевидная вещь» – это проблема дизайна
Умножение — вещь, неочевидная для первоклассника. Надо ли делать язык без умножений или учить первоклассников умножению?
На сколько помню, целью Котлина было облегчение разработки и защита от глупых ошибок. А в результате одни глупые ошибки заменили на другие.
Это суждение — следствие опыта разработки на котлине, или вы просто посмотрели пазлеры?
- Это не паззлер. Любой оператор?.. вернет nullable тип, это очевидно.
Автора предложения об автоматической конвертации null в false надо вернуть обратно в яваскрипт и не выпускать до просветления. - И это не пазлер. Для nullable типа могут быть методы расширения, это тоже очевидно.
- И снова не пазлер. Очевидное решение по скрещиванию null-safe языка с null-unsafe JVM.
- И опять не пазлер. Разница между методом и вызовом также очевидна.
- Первый реальный пазлер. С лямбдами это вечный вопрос и в каждом языке он решается по-своему.
- Не пазлер. Результат рекурсии немного предсказуем.
- Снова не пазлер. Ибо тезис "самое лучшее определение unit — это void." неверен. void — это не прагматизм, а костыль, заботливо перенесенный из си.
- Второй реальный пазлер и первый возможный претендент на ошибку дизайна. Правда сравнение с яваскриптом некорректно. В котлине значение this известно на этапе компиляции.
- Третий реальный пазлер на типичной проблеме приоритета и ассоциативности операций. Ошибкой дизайна не является, код паззлера выглядит плохо и имеет заведомо лучшую альтернативу.
- Не пазлер. Код сразу выглядит плохо, используя зависимость val от var. Конец снова предсказуем.
- Не пазлер, компилятор бдит, жаль только warning а не error.
Итоги: 3 реальных пазлера из 11, 1 (одна) возможная ошибка дизайна. В остальных случаях результат или очевиден сразу, или плохой код и выглядит плохо (для человека, а нередко и для компилятора), что и требуется для защиты от глупых ошибок.
я не спец по котлину, но 9ый и 10ый пазлеры для меня выглядят как бага языка
Пазлер 9 — спорно. Можно рассматривать и так, и так. Возможно, JetBrains выбрали менее удобный вариант, но лично я предпочитаю использовать ключевое слово when, если веток больше чем 2.
Пазлер 10 — не баг, однозначно. Из доки следует, что делегат это объект с вот такими методами:
//на чтение
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return "$thisRef, thank you for delegating '${property.name}' to me!"
}
//на запись
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("$value has been assigned to '${property.name} in $thisRef.'")
}
У интерфейса kotlin.collections.Map нет таких методов, зато есть соответствующие экстеншн функции в файле MapAccessors.
То есть синтаксис объявления делегата по мапе не магия, которая от нас сокрыта, а вполне традиционный для котлина способ делегирования.
when
:fun printNumber(num: Int) {
when {
num < 0 -> "negative"
num > 0 -> "positive"
else -> "zero"
}.let { println(it) }
}
Кстати, если в исходном примере встать на первый if и применить intention «Replace 'if' with 'when'», то картина почему всё так было, становится яснее:
when {
num < 0 -> "negative"
else -> if (num > 0) {
"positive"
} else {
"zero"
}.let { println(it) }
}
if (s?.isEmpty() ?: false) println(«true»)Студия уже давно предлагает такое исправлять на
if (s?.isEmpty() == true) println("true")
null – это не булевый тип, т.е. эта запись недоступна (как в котлине, так и в джаве).
String s = null;
if ( s?.isEmpty() == true ) {
// do something
}
В этом случае s?.isEmpty() вернет null.
Но null и true сравнивать запрещено.
null нельзя привести в boolean. А если это сделать – это ослабит типизацию, что повлечет ряд других проблем.
Изначально обсуждался следующий пример:
String s = null;
Это вообще не котлин.
Правильно как в статье:
val s: String? = null
А вторая строка — наоборот совершенно правильная
if ( s?.isEmpty() == true )
- s имеет тип String? (nullable String)
- s?.isEmpty() имеет тип Boolean? (nullable Boolean)
- Константа true принадлежит как типу Boolean, так и типу Boolean?
- Конкретный тип котлин выводит по контексту — слева от равенства Boolean?
- Соответственно справа будет тоже Boolean?
- Для этого типа можно сравнить true с null
Ссылка для проверки онлайн:
https://try.kotlinlang.org/#/UserProjects/2f15ok94p3k8lse1fj96t6apr0/2032nrf2rjpjvp11t1307onr7m
null нельзя привести в boolean
Зато boolean
можно привести в boolean?
С Котлиным такой проблемы нет
Котлин это не фамилия :)
А вообще для kotlin-программиста большинство этих паззлеров не то что известно — это очевидное поведение языка :) Самый страшный паззлер 11, но и вкупэ с Intellij Idea страх перед возможностью напороться на паззлеры сам собой рассеивается.
Kotlin, puzzlers and 2 Kekses: Вы уверены, что знаете, как ведет себя Kotlin?