Upgrade to Pro — share decks privately, control downloads, hide ads and more …

[SnowOne 2025] Роман Елизаров: Уроки Kotlin, ил...

[SnowOne 2025] Роман Елизаров: Уроки Kotlin, или Зачем создавать еще один язык программирования

В мире есть множество языков программирования. Казалось бы, для каждой задачи уже какой-то язык есть — просто бери и используй. Так зачем же делать еще один? Зачем мы создавали язык Kotlin? Чего нам не хватало в Java? Является ли Kotlin теперь идеальным языком? Чего не хватает в Kotlin?

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

Видео: https://youtu.be/huPZqkb-Sb8

Avatar for jugnsk

jugnsk

May 07, 2025
Tweet

More Decks by jugnsk

Other Decks in Programming

Transcript

  1. Обо мне • В индустрии программирования с 2000 года •

    Разрабатывал всякое высоконагруженное ПО @ Devexperts • Преподаю параллельное программирование @ Санкт-Петербургский ИТМО • Председатель жюри @ Northern Eurasia Contest / ICPC • Руководил дизайном и командой языка Kotlin @ JetBrains • Улучшаю опыт разработчиков @ Yandex (БГ Екома и Райдтеха)
  2. Какие языки сейчас популярны? • PYPL (частота поиска по “xxx

    tutorial”) 1. Python 2. Java 3. JavaScript 4. C/C++ 5. C# … • RedMonk (GitHub + SO) 1. JavaScript 2. Python 3. Java 4. PHP 5. C# … CSS
  3. Управление памятью int *a = calloc(n * sizeof(int)); free(a); vector<int>

    a(n); auto a = make_unique<vector<int>>(n); auto a = make_shared<vector<int>>(n); a = [0] * n val a = IntArray(10)
  4. “программы должны писаться для того, чтобы их читали люди, и

    лишь во вторую очередь для выполнения машиной” - Харольд Абельсон, Структура и интерпретация компьютерных программ
  5. function updateOrder() function updateOrder(order, address) function updateOrder(order: PlainOrder, address: MailAddress):

    PlainOrder function updateOrder($1, $2) function updateOrder(order: PlainOrder, address: MailAddress?): PlainOrder Типизация!
  6. Было раньше int count = ... double average = ...

    List<String> strings = ... Map<Warehouse, List<OrderItem>> items = ...
  7. Стало с выводом var count = ... var average =

    ... var strings = ... var items = ...
  8. Стало с выводом var count = ... var average =

    ... var strings = ... Map<Warehouse, List<OrderItem>> items = ...
  9. Типы справа! var count = ... var average = ...

    var strings = ... var items: Map<Warehouse, List<OrderItem>> = ...
  10. Почитаем код… Map<Warehouse, Double> totalWeight(List<Order> orders) { var result =

    new HashMap<Warehouse, Double>(); for (var order : orders) { for (var item : order.getItems()) { var sum = result.get(item.getWarehouse()); if (sum == null) { sum = 0.0; } result.put(item.getWarehouse(), sum + item.getWeight()); } } return result; }
  11. Почитаем код… Map<Warehouse, Double> totalWeight(List<Order> orders) { var result =

    new HashMap<Warehouse, Double>(); for (var order : orders) { for (var item : order.getItems()) { var sum = result.get(item.getWarehouse()); if (sum == null) { sum = 0.0; } result.put(item.getWarehouse(), sum + item.getWeight()); } } return result; }
  12. Почитаем код… Map<Warehouse, Double> totalWeight(List<Order> orders) { var result =

    new HashMap<Warehouse, Double>(); for (var order : orders) { for (var item : order.getItems()) { var sum = result.get(item.getWarehouse()); if (sum == null) { sum = 0.0; } result.put(item.getWarehouse(), sum + item.getWeight()); } } return result; }
  13. Почитаем код… Map<Warehouse, Double> totalWeight(List<Order> orders) { var result =

    new HashMap<Warehouse, Double>(); for (var order : orders) { for (var item : order.getItems()) { var sum = result.get(item.getWarehouse()); if (sum == null) { sum = 0.0; } result.put(item.getWarehouse(), sum + item.getWeight()); } } return result; }
  14. Почитаем код… Map<Warehouse, Double> totalWeight(List<Order> orders) { var result =

    new HashMap<Warehouse, Double>(); for (var order : orders) { for (var item : order.getItems()) { var sum = result.get(item.getWarehouse()); if (sum == null) { sum = 0.0; } result.put(item.getWarehouse(), sum + item.getWeight()); } } return result; }
  15. Почитаем код… Map<Warehouse, Double> totalWeight(List<Order> orders) { var result =

    new HashMap<Warehouse, Double>(); for (var order : orders) { for (var item : order.getItems()) { var sum = result.get(item.getWarehouse()); if (sum == null) { sum = 0.0; } result.put(item.getWarehouse(), sum + item.getWeight()); } } return result; }
  16. Почитаем код… Map<Warehouse, Double> totalWeight(List<Order> orders) { var result =

    new HashMap<Warehouse, Double>(); for (var order : orders) { for (var item : order.getItems()) { var sum = result.get(item.getWarehouse()); if (sum == null) { sum = 0.0; } result.put(item.getWarehouse(), sum + item.getWeight()); } } return result; }
  17. Почитаем код… Map<Warehouse, Double> totalWeight(List<Order> orders) { var result =

    new HashMap<Warehouse, Double>(); for (var order : orders) { for (var item : order.getItems()) { var sum = result.get(item.getWarehouse()); if (sum == null) { sum = 0.0; } result.put(item.getWarehouse(), sum + item.getWeight()); } } return result; }
  18. Почитаем код… Map<Warehouse, Double> totalWeight(List<Order> orders) { var result =

    new HashMap<Warehouse, Double>(); for (var order : orders) { for (var item : order.getItems()) { var sum = result.get(item.getWarehouse()); if (sum == null) { sum = 0.0; } result.put(item.getWarehouse(), sum + item.getWeight()); } } return result; } Императивный стиль
  19. Лучше Map<Warehouse, Double> totalWeight(List<Order> orders) { return orders.stream() .flatMap(order ->

    order.getItems().stream()) .collect( groupingBy(OrderItem::getWarehouse, summingDouble(OrderItem::getWeight))); }
  20. Лучше Map<Warehouse, Double> totalWeight(List<Order> orders) { return orders.stream() .flatMap(order ->

    order.getItems().stream()) .collect( groupingBy(OrderItem::getWarehouse, summingDouble(OrderItem::getWeight))); }
  21. Лучше Map<Warehouse, Double> totalWeight(List<Order> orders) { return orders.stream() .flatMap(order ->

    order.getItems().stream()) .collect( groupingBy(OrderItem::getWarehouse, summingDouble(OrderItem::getWeight))); }
  22. Лучше Map<Warehouse, Double> totalWeight(List<Order> orders) { return orders.stream() .flatMap(order ->

    order.getItems().stream()) .collect( groupingBy(OrderItem::getWarehouse, summingDouble(OrderItem::getWeight))); }
  23. Лучше Map<Warehouse, Double> totalWeight(List<Order> orders) { return orders.stream() .flatMap(order ->

    order.getItems().stream()) .collect( groupingBy(OrderItem::getWarehouse, summingDouble(OrderItem::getWeight))); }
  24. Лучше fun totalWeight(orders: List<Order>): Map<Warehouse, Double> = orders .flatMap {

    it.items } .groupingBy { it.warehouse } .fold(0.0) { acc, item -> acc + item.weight } Функциональный стиль
  25. Null reference “I call it my billion-dollar mistake. It was

    the inven2on of the null reference in 1965. At that 2me, I was designing the first comprehensive type system for references in an object oriented language ALGOL W. My goal was to ensure that all use of references should be absolutely safe, with checking performed automa2cally by the compiler. But I couldn't resist the tempta2on to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabili2es, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.” Sir Tony Hoare
  26. Эволюция к более лучшим языкам • Больше null-safety • Больше

    функционального подхода • Больше неизменяемых значений • Больше строгой типизации • Больше автоматического управления памятью
  27. Эволюция к более лучшим языкам • Больше null-safety • Больше

    функционального подхода • Больше неизменяемых значений • Больше строгой типизации • Больше автоматического управления памятью СТОП
  28. Нельзя удобно запихать всё в один язык! Задача Модель Алгоритм

    Представление Память Инструкции Языки низкого уровня Системные языки Прикладные языки
  29. Но ведь в 2025 году уже мы знаем как делать

    языки лучше и они у нас есть! Ведь правда?
  30. Языки-наследники это компромисс! • ЗА • Получаем доступ к готовой

    экосистеме • ПРОТИВ • Наследуем много исторических проблем
  31. Примеры из Котлина: строки fun main() { val s =

    "😭" println(s.encodeToByteArray().size) !// 4 println(s.length) !// 2 } 😭
  32. Примеры из Котлина: инициализация и наследование abstract class Parent {

    abstract val kind: String init { println("Initializing $kind") } } class Child : Parent() { override val kind = "Child" } 😱
  33. Сделать новый язык с чистого листа без исторического наследия Унаследовать

    Java экосистему со всеми её библиотеками, инструментами и … недочетами
  34. Эволюция к более лучшим языкам • Больше null-safety • Больше

    функционального подхода • Больше неизменяемых значений • Больше строгой типизации? • Больше автоматического управления памятью
  35. AI