Pull to refresh

Comments 24

В этом Kotlin похож на JavaScript. Как в JavaScript, в Kotlin можно достичь того состояния, когда вы уже не знаете, что такое this.

*что-то вычеркивает в записной книжке
UFO just landed and posted this here
Разница в том, что в JavaScript this определяется динамически, и без трассировки (хотя бы мысленной) не обойтись, а в Kotlin this можно вычислить статически, просто «на глаз» это не всегда очевидно. Иногда помогает расстановка явных скоупов this@Something
К сожалению, с практической точки зрения, эти «прикольные фичи», на самом деле – «долбанные ошибки дизайна».

Они есть во всех языках, но в некоторых для этого нужно сделать что-то невероятное.
А в Котлине, как показывает автор, на эти грабли можно будет наступить на каждом шагу :-(

Язык очень интересный, но складывается впечатление, что взяли все возможные фичи со всех языков и попытались все их уместить в один язык. В результате имеем такие вот забавные пазлеры.
«Неочевидная вещь» это не то же самое, что «долбанная ошибка». И да, другим языкам тут лучше помолчать, потому что у них заскоков бывает ещё больше.
Вы урезали контекст, изначально было: «Долбанная ошибка дизайна».
«Неочевидная вещь» – это проблема дизайна, т.е. – «Долбанная ошибка дизайна».

Тут хорошо подойдет аналогия с UI/UX: все должно быть максимально просто и очевидно. Если это не так, значит есть проблема. Язык программирования – это товар, а Программист – потребитель/пользователь.

Если Вы не согласны с этим утверждением, тогда ответьте на вопрос: почему каждый год выходят десятки новых языков и почему каждый раз, когда крупная компания выпускает свой язык, то подымается хайп?
Kotlin, Scala, Groovy, TypeScript, Elm, CoffeScript, Rust, Go, Swift, etc.

На сколько помню, целью Котлина было облегчение разработки и защита от глупых ошибок. А в результате одни глупые ошибки заменили на другие.
«Неочевидная вещь» – это проблема дизайна

Умножение — вещь, неочевидная для первоклассника. Надо ли делать язык без умножений или учить первоклассников умножению?


На сколько помню, целью Котлина было облегчение разработки и защита от глупых ошибок. А в результате одни глупые ошибки заменили на другие.

Это суждение — следствие опыта разработки на котлине, или вы просто посмотрели пазлеры?

  1. Это не паззлер. Любой оператор?.. вернет nullable тип, это очевидно.
    Автора предложения об автоматической конвертации null в false надо вернуть обратно в яваскрипт и не выпускать до просветления.
  2. И это не пазлер. Для nullable типа могут быть методы расширения, это тоже очевидно.
  3. И снова не пазлер. Очевидное решение по скрещиванию null-safe языка с null-unsafe JVM.
  4. И опять не пазлер. Разница между методом и вызовом также очевидна.
  5. Первый реальный пазлер. С лямбдами это вечный вопрос и в каждом языке он решается по-своему.
  6. Не пазлер. Результат рекурсии немного предсказуем.
  7. Снова не пазлер. Ибо тезис "самое лучшее определение unit — это void." неверен. void — это не прагматизм, а костыль, заботливо перенесенный из си.
  8. Второй реальный пазлер и первый возможный претендент на ошибку дизайна. Правда сравнение с яваскриптом некорректно. В котлине значение this известно на этапе компиляции.
  9. Третий реальный пазлер на типичной проблеме приоритета и ассоциативности операций. Ошибкой дизайна не является, код паззлера выглядит плохо и имеет заведомо лучшую альтернативу.
  10. Не пазлер. Код сразу выглядит плохо, используя зависимость val от var. Конец снова предсказуем.
  11. Не пазлер, компилятор бдит, жаль только warning а не error.

Итоги: 3 реальных пазлера из 11, 1 (одна) возможная ошибка дизайна. В остальных случаях результат или очевиден сразу, или плохой код и выглядит плохо (для человека, а нередко и для компилятора), что и требуется для защиты от глупых ошибок.

Настоящий паззлер — это Пазлер 11. Все остальное — это ожидаемое поведение.

я не спец по котлину, но 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.
То есть синтаксис объявления делегата по мапе не магия, которая от нас сокрыта, а вполне традиционный для котлина способ делегирования.
Люди, которые хотят автоматическое приведение Nothing к False, сами не знают чего хотят.
Отличная статья, но вот этот программистский новояз реально режет глаза — «пушит», «тулинг», «кейворд», и т.д. Неужели нельзя найти подходящие русскоязычные термины? Или вы боитесь что будет как в примере с «фу, знач, печать»? Спешу вас успокоить, вы только выиграете, если будете периодически чистить свою речь.
И чтобы лишний раз не стрелять себе в ногу, в примере 9 лучше писать с 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 == true,
null – это не булевый тип, т.е. эта запись недоступна (как в котлине, так и в джаве).
Такое сравнение допустимо: если одно из слагаемых будет равно null, то результат будет равен false. А вот null == null, ожидаемо вернет true.
Будет, но это сравнение двух значений типа bool? — вполне рабочее.
Изначально обсуждался следующий пример:
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 )

  1. s имеет тип String? (nullable String)
  2. s?.isEmpty() имеет тип Boolean? (nullable Boolean)
  3. Константа true принадлежит как типу Boolean, так и типу Boolean?
  4. Конкретный тип котлин выводит по контексту — слева от равенства Boolean?
  5. Соответственно справа будет тоже Boolean?
  6. Для этого типа можно сравнить true с null

Ссылка для проверки онлайн:
https://try.kotlinlang.org/#/UserProjects/2f15ok94p3k8lse1fj96t6apr0/2032nrf2rjpjvp11t1307onr7m

С Котлиным такой проблемы нет

Котлин это не фамилия :)
А вообще для kotlin-программиста большинство этих паззлеров не то что известно — это очевидное поведение языка :) Самый страшный паззлер 11, но и вкупэ с Intellij Idea страх перед возможностью напороться на паззлеры сам собой рассеивается.
UFO just landed and posted this here
Sign up to leave a comment.