Комментарии 81
Ура! Отличный релиз, спасибо разработчикам и всей команде Kotlin!
Нажимаю запуск. Ни для какого типа сборки не работает. Выдает портянку ошибок.
Конкретно этот пример работает для версии компилятора 1.0.6 (можно выбрать внизу вместо 1.1). Вероятная причина в том что Kotlin APIs для JavaScript слегка поменялись между 1.0 и 1.1. Примеры с переносимым кодом запускаются как на JVM, так и на JS под любой версией.
Отдельное спасибо что добавляете фичи для любителей функционального программирования.
Недавно на хабре опубликовали серию видео уроков
https://habrahabr.ru/post/321600/
coroutines — ИМХО, намного лучше чем в .Net
Я бы сам так же сделал =)
А можете пояснить этот момент для несведующих? Я из документации не очень понял в чем, по сути, отличие между async\await из .NET
В документации не раскрыта вся суть. А суть в том, что корутины в Kotlin не привязаны ни к конкретным библиотеками, ни к конкретным типам. async/await из примера — это просто библиотечные функции, можно писать свои для различных фреймворков. И ещё — generate/yield — это тоже библиотечные функции, реализованные поверх того же механизма корутин. Подчеркну, что там нет никакой внутренней магии специально для разработчиков stdlib, кто угодно может написать свои реализации generate/yield и async/await.
Судя по документации — нельзя вызвать suspendable из не suspendable (что в общем-то вполне очевидно). В своих примерах они вызывают все сначала через runBlocking, а внутри уже все suspendale. Вообще выглядит как абсолютно то же самое с другим синтаксисом — пулы и диспатчеры соответствуют пулам и шедулерам в .net. Deferred< T > -> Task< T >, но как раз из-за синтаксиса разница существенная.
В целом выглядит так что с точки зрения синтаксиса в котлине асинхронщина будет в большинстве случаев удобнее в использовании (чему я как C# разработчик завидую). Плюс в C# есть одна проблема — асинхронные геттеры и сеттеры — ибо они в данный момент попросту невозможны, при этом есть entity framework у которого в lazy-loading активно используется блокирование.
Но и у дотнета есть преимущество — все нужное лежит в базовой библиотеке, ну и разработчики асинхронщины могут изменить базовую библиотеку (т.к. это почти что одни и те же люди) чтобы эта самая асинхронщина нормально поддерживалась. То есть в дотнете есть Task и его используют все — как сами ms, так и разрабы сторонних библиотек. Также в дотнете к базовому классу Stream они приделали — Read/WriteAsync, а как будут менять стандартную библиотеку jetbrains?
Похоже вы меня не поняли. Асинхронщина была и в дотнете еще до async/await. И когда в дотнете запилили новый паттерн асинхронности — таски, async/await то базовую библиотеку изменили — добавили методы которые возвращают Task. То есть пользоваться базовой библиотекой стало в кайф.
В яве тоже есть non-blocking io. Но вот получается что новый асинхронный паттерн разрабатывают jetbrains, вследствие чего вопрос — как новый паттерн (suspendable) будет кореллировать с классами стандартной библиотеки?
Как раз одним из главных приоритетов при разработке корутин и была бесшовная интеграция с существующими библиотеками. В отличие от .NET, Kotlin не привязывает реализацию корутин к конкретным классам вроде Task. suspend-функцию можно написать для любой имеющейся библиотеки.
Когда вы запилите LINQ и уже можно будет мигрировать .Net -> Kotlin не расставаясь с привычными фичами?
Разрешите поинтересоваться, а для чего вы используете LINQ в C# и с каким именно его фичами вы не хотели бы расставаться?
Работа с коллекциями в Kotlin на полную катушку через уже традиционные map/filter, по-моему даже удобнее чем любой SQL. Для доступа к базам данных и статическому формированию SQL-запросов есть пара активных библиотек, например Exposed одна из более экспериментальных.
Можно ли будет в обозримом будущем получать краткое описание методов прямо в IDEA без гугления.
К примеру описание функций let, apply, also из сорцов не получить, а очень хочется.
Откуда ts2kt сейчас (либо в будущем) будет брать nullability информацию из дескрипторов, которые этой информации лишены? Есть ли какая-то механика, либо будет организована работа только для дескрипторов с оной?
Есть ли публичном доступе roadmap для KotlinJS?
Чего можно ждать в обозримом будущем от KotlinJS?
В частности интересует момент с Mixin-ами.
Будет ли возможность помечать методы интерфейса как уже реализованные?
Библиотека kotlin.js — 1Mb, планируется ли существенно сократить его размер?
Возможен ли будет вариант, когда только нужная функциональность будет реализована напрямую в финальном js-файле? К примеру, чтобы Hello World не тянул за собой метровую зависимость, а все нужное содержал уже внутри.
Спасибо.
Чего можно ждать в обозримом будущем от KotlinJS?
Инкрементальной компиляции, минификации aka dead code elimination (так же известный под названием tree shaking, которое меня немного выбешивает), куча примеров кода, работающего с современными фреймворками (такими, как React) и документации. Это совсем ближайшее время, буквально несколько месяцев. Дальше пока не планировали (или по крайней мере, я не в курсе). Так же надеюсь, что будет время немного улучшить интероп, например, завести правильные external enum. Ещё есть пользователи, которые очень хотят генерацию микромодулей и ES6, мы держим это в голове, и активно обсуждаем, но конкретных сроков у нас сейчас нет.
Ещё в Kotlin есть такой минус, что достаточно неудобно разрабатывать проект, в котором есть общая кодовая база между JS и JVM. Этот момент непосредственно к JS не относится, там больше по части общекомпиляторной работы и всякого тулинга. Я так понимаю, что мы над этим будем работать в ближайшее время, но по срокам пока непонятно, скорее всего, в обозримом будущем удастся выпустить common-модули в экспериментальном режиме.
Будет ли возможность помечать методы интерфейса как уже реализованные?
Не вполне понятно, что вы понимаете под этим. Можете пример из мира JS (и по возможности, пример деклараций в TS)?
Библиотека kotlin.js — 1Mb, планируется ли существенно сократить его размер?
Сократить — нет, подружить вывод компилятора с различными минификаторами или разбить на кусочки поменьше — возможно. Конечно, мы понимаем, что такая здоровенная библиотека — это плохо. Кстати, после uglify она где-то в 2 раза ужимается, а после gzip и того более.
Возможен ли будет вариант, когда только нужная функциональность будет реализована напрямую в финальном js-файле? К примеру, чтобы Hello World не тянул за собой метровую зависимость, а все нужное содержал уже внутри.
Зачем, если для этого есть стандартные инструменты? У нас в JetBrains для внутренних разработок успешно используют Kotlin в связке с webpack, Kotlin компилирует, webpack — пакует. Как-то нелогично тянуть в компилятор линковку. Есть какая-то небольшая вероятность, что мы захотим написать свой бандлер, но в ближайших обозримых планах ничего такого нет.
Не вполне понятно, что вы понимаете под этим. Можете пример из мира JS (и по возможности, пример деклараций в TS)?
TS — https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/yfiles
http://docs.yworks.com/yfileshtml/#/api/yfiles.collections.IEnumerable у которого всего один абстрактый метод, а все остальные реализованы, сейчас его можно только как абстракный класс, иначе с наследованием беда.
И пример с http://docs.yworks.com/yfileshtml/#/api/yfiles.geometry.OrientedRectangle, у которого в дескрипторе всего 2 интерфейса, но оба из них частично реализованы.
Да, такие планы есть.
видимо как раз из за того что не хватает информации о типах.
В том-то и беда, что "видимо". GCC достаточно плохо работает на stdlib Kotlin, и пока не вполне очевидно почему. Возможно, дело в типах, возможно, в чём-то другом. Это вопрос требует исследования, и мы планируем потратить на них какое-то время.
Можно ли будет в обозримом будущем получать краткое описание методов прямо в IDEA без гугления.
К примеру описание функций let, apply, also из сорцов не получить, а очень хочется.
А в чем пробоема? "Quick Documentation" должен работать.
Откуда ts2kt сейчас (либо в будущем) будет брать nullability информацию из дескрипторов, которые этой информации лишены?
В декларациях на TypeScript такая информация может присутстовать, аля Type | null
и конвертор это пользуется.
На текущий момент плагин 1.1.0-beta-38-IJ2016.3-1 — последний кто kts файлы без проблем отображает.
Все следующие жалуются на функции стандартных типов.
Какие преимущества есть у Kotlin по сравнению с TypeScript, чтобы ради них идти на такие жертвы?
(промахнулся)
Жертвы действительно есть:
- Компилятор (пока) работает на JVM, соответственно, чтобы полноценно компилироваться в JS, не хватит только node.js/webpack, нужно ещё ставить JVM. Для JS-разработчика, у которого стоит нода, но не стоит JVM, это может стать препятствием.
- У нас (пока) нет лоадера для webpack. Т.е. нужно настраивать gradle для компиляции Kotlin и webpack для всего остального. Это, конечно же, не касается пользователей какого-нибудь google closure compiler.
- Система типов Kotlin изначально проектировалась с прицелом на JVM, система типов TypeScript — с прицелом на JS. В итоге, не всегда Kotlin так же хорошо ложится на JS, как TypeScript. Например, в Kotlin поддерживается перегрузка функций по типу параметров, чего нет в JS (и следовательно, в TS). Таким образом, по умолчанию Kotlin при компиляции функций с параметрами дописывает к их названию некий суффикс, полученный страшным алгоритмом. Конечно, есть аннотация
@JsName
, которая позволяет явно задать имя функции в JS. Другой пример — отсутствие union types в нашей системе типов. - Мы тащим с собой жирный рантайм (1,2 мб), и (пока) не умеем из него вырезать неиспользуемые части.
- Мы (пока) не умеем компилироваться инкрементально.
Как видите, часть проблем здесь из разряда "пока не успели сделать" (в основном по тулингу, у нас 1.2 как раз будет на нём фокусироваться), а часть "ничего нельзя поделать". В первом случае надо подождать, во втором — мы пытаемся минимизировать боль от последствий.
Если у кого-то есть что-то ещё добавить к списку — пожалуйста, отписывайтесь к комментам, мы будем рады перечисленные недостатки устранить.
Разумеется, так сделать можно, и на первых порах мы возможно так и поступим. И тут придут апологеты TypeScript и начнут сравнивать размеры npm-пакетов. В перспективе, возможно, удастся скомпилировать kotlinc с помощью какого-нибудь AOT-компилятора или полностью вырезать из компилятора все зависимости от Java.
Я так понимаю, возможность писать на одном языке бэкэнд и фронт-энд для Android, iOS (скоро) и веба. TS компилируется только в JS. Конечно, можно TS на ноде гонять, но не всем подходит нода. Опять же, можно TS гонять на Cordova/React Native, но нативное приложение должно шустрее работать. Плюс синтаксические вкусности, которых нет в TS:
- declaration site/use site variance;
- нелокальные return-ы (например, можно взять и сделать return из вызывающей функции прямо из лямбды, переданной в функцию map);
- смарткасты;
- богатые возможности для построения DSL;
- навороченные корутины
Ну и не забывайте про тех пользователей, которые уже используют Kotlin на JVM, и хотят на нём же писать и веб-клиент (либо с нуля, либо переписать на нём имеющийся JS-клиент).
В принципе, тот факт, что мы не сможем поспеть за TS в плане лёгкости интеропа и тулинга (да и TS уже банально прочно занял нишу), лично мне понятен. Мой персональный приоритет — это создание именно такого языка, который позволял бы легко бы писать fullstack-приложения. К сожалению, это пока не совсем так, но я надеюсь, мы движемся в правильном направлении и скоро Kotlin станет полноценным языком для fullstack-разработки.
С другой стороны, мы не сможем перегнать TS, но нам есть, куда расти. Задачей к 1.1 было стабилизироваться, т.е. задизайнить минимальный набор необходимых фич, причём так, чтобы потом не ломать совместимость. Ну и конечно, пофиксить баги и реализовать недостающие языковые фичи, доступные в Kotlin JVM. Некоторыми вещами в интеропе пришлось пожертвовать (например, теми же строковыми enum-ами), но никто не мешает их сделать к следующим версиям языка.
Насчёт Silverlight не знаю, а вот GWT я успешно использовал в production на протяжении трёх лет и очень был доволен. Но у GWT есть фатальный недостаток — он не понимает Kotlin. Хочу пояснить — я хорошо знаю JavaScript и вполне способен писать приложения на каком-нибудь Angular. Проблема в том, что я этого делать не хочу:
- Мне JavaScript банально меньше нравится.
- Язык — это не только сам язык, но и ещё целая куча технологий вокруг него — библиотеки, системы сборки, IDE, линтеры и т.п. Лично мне неприятно всё время переключать в голове контекст с одного на другое. Да и объём знаний там немаленький, пришлось кучу времени потратить, чтобы переключиться с Java на JavaScript. И собственно язык — это пара дней работы, вся остальная куча времени пришлась на ту самую пресловутую экосистему.
JavaScript без своей экосистемы — не очень вкусен. Постоянно поддерживать интеграцию с ней то же мало приятного. Позавчера Grunt, вчера Gulp, сейчас Webpack. Как быть с новыми фичами языка? Это все ограничивающие факторы. Для JS разве что TypeScript, ибо он хитрое надмножество. Но это в любом случае еще один уровень абстракции, за который надо платить.
Я то же не любил JS. Потом смирился :) И с удовольствием использую его на фронте и C# в бэке. Поэтому если мне прижмет использовать redux-observable, я не буду ломать себе голову как мне это и интегрировать с какой-то абстракцией.
Со стороны это похоже на попытку сделать универсальный инструмент для всего и всех. На текущем этапе жизни я уже в такое не верю :)
JavaScript без своей экосистемы — не очень вкусен.
GWT прекрасно живёт в своей экосистеме. Сборка — Maven, хранилище артефактов — тот же maven central или jcenter, линтеры — checkstyle и PMD, библиотеки и фреймворки — специально написанные для GWT или портированные с "большой" Java, либо обёртки вокруг JS-ных библиотек. Минификацию делает сам (причём сильно лучше новомодных webpack-ов), модульность на уровне модулей Maven.
Постоянно поддерживать интеграцию с ней то же мало приятного.
Мне кажется, это утверждение из разряда "у страха глаза велики". Там достаточно много всего, но интегрироваться с этим не так сложно, есть вещи более-менее устоявшиеся. Ну и да, всё "быстро меняется" в восторженных статьях на Хабре, а весь мир по-прежнему сидит на jQuery.
Со стороны это похоже на попытку сделать универсальный инструмент для всего и всех.
Нет, это попытка сделать инструмент для тех, кто хочет fullstack на Kotlin. Кому нормально писать фронтэнд на JS, тот и дальше будет писать на JS.
Тут все просто — Frontent разработчики используют React/NG2/Vue и тд. Зачем им GWT и подобные абстракции? Все и так отлично. Еще и WebAssembly завезли :D
Вообще все давно изменилось :) И таки да, это геморой еще тот. Сам сталкивался с тайпингами в TS, когда он еще не развился до текущего уровня. И это с учетом, что он все таки близок к JS.
Зачем? Если это будет сколько нибудь сложный UI — ну его в пень такой fullstack ;) Народ запаритесь искать и будете бороться с corner-case'ами.
Тут все просто — Frontent разработчики используют React/NG2/Vue и тд. Зачем им GWT и подобные абстракции? Все и так отлично.
Во-первых, я же уже сказал — ИМХО, компилятор из Kotlin в JavaScript больше нужен Kotlin-разработчикам, которые захотели ещё писать фронтэнд, а не фронтэнд-разработчикам, которые уже счастливы с JS.
Во-вторых, если так мыслить, то вообще никогда ничего нового не будет появляться. В 80-е разработчики прекрасно жили с Cobol. А сейчас люди прекрасно сидят на Java, так что, теперь из этого следует, что Kotlin не нужен? Нет, оказалось, что на это есть какой-то спрос, нашлась ниша. Возможно, найдётся ниша для компилятора в JavaScript. Пока самая очевидная — это та, которую я назвал, но реальность как всегда такова, что выстрелить язык может там, где никто этого не ожидал. Глупо не попытаться использовать шанс, если он есть. Ведь хуже будет, если Scala.js выстрелит, в этом случае Kotlin придётся запрыгивать в уходящий поезд.
Еще и WebAssembly завезли
А это вообще мимо кассы. WebAssembly — это средство для бородатых дяденек, пишущих на C и C++ запускать свои шустрые программы в браузере. Мне кажется, пересечение с "традиционным" фронтэндом и всей его экосистемой — минимальное. Вот это отличный шанс туда запрыгнуть новым многообещающим языкам.
Компиляторы в JS отнюдь не новинка ;) Никто не говорит про то, что не надо развиваться. Вопрос в скоупе и необходимости тратить ресурсы на него. Если у Kotlin что-то получится — будет хорошо. Scala пусть со своим sbt разберется, перед тем как на js взлетать :)
https://github.com/kg/ilwasm :D
Мне кажется, пересечение с "традиционным" фронтэндом и всей его экосистемой — минимальное.
А мне кажется, что очень быстро зайдёт в "традиционный". Хотя бы просто как замена и(или) дополнение к минификаторам.
WebAssembly ещё очень далеко до того, чтобы на нём сделать полноценную реализацию движка JS. Сейчас там нет ни GC (и сложно сделать свой, т.к. нет доступа к стеку), ни вообще какого-либо способа пропатчить код в рантайме или повыставлять защиту страниц памяти.
По поводу эффективности бинарного формата в плане размера. Если интересно, у меня есть свой экспериментальный транслятор байт-кода Java в WebAssembly, вот работающий пример приложения. Так вот, размер JavaScript — 274 кб, размер WebAssembly — 488 кб.
Kotlin же тянет с собой мегабайтную библиотеку
Я же уже писал — мы постепенно решим эту проблему
в генерированном коде черт ногу сломит
А можно про это поподробнее? Что именно непонятно в коде? Кроме очевидных вещей вроде манглирования идентификаторов (что на мой взгляд не сильно страшно) назовите хотя бы несколько пунктов.
Далее, а зачем генерируемый год должен быть читаемым? Вы часто смотрите на машинный код, сгенерированный каким-нибудь gcc?
Кроме того, TS на порядок проще.
И про это можно подробнее? Опять же, хотя бы несколько пунктов.
Далее, а зачем генерируемый год должен быть читаемым?
Для отладки непосредственно в среде исполнения (читай — браузере). Среда бросает исключение, например, и ссылается, как ни странно, на сгенерированный код, разве что source map есть и нормально подключился.
Это было сделано из соображений удобства и производительности. Удобство в том что не нужно дополнительно звать коллектор в конце. Производительность проявляется в том что на маленьких коллекциях (до 10`000), которых большинство, локальность операций по памяти важнее чем выделение-освобождение списков.
И как уже упомяналось, в любой момент можно перейти к ленивой семантике с asSequence()
или даже к Java8-streams с asStream()
Что такое «локальность операций по памяти»?
Это позволяет разрабатывать веб-приложение целиком на Kotlin
В смысле фронт будет компилироваться в JS, а бэк в JVM? Или можно и бэк скомпилировать для запуска под нодой, чтобы JVM в продакшене не было?
Либо if будет его заменой еще долго?
P.S. Режут глаз места, где тернарник просится, а приходится писать if.
Летом прошлого года вопрос о тернарном операторе был открыт.
Андрей Бреслав на одной из встреч говорил о том, что в классическом виде (? и :) он в Котлин уже не попадет, а в каком виде он может войти и вообще войдет ли — вопрос открытый.
Собственно хочется знать не закрыт ли этот вопрос окончательно.
Что вы вокруг этой темы все скачете, развели тут бардак XD
Неужели так сложно писать код вида:
$base = new ThreadBase();
$thread = new Thread(function () { ...some_code… });
$base->run(thread, thread2,… threadn);
$base->when(thread, thread2,… threadn)->done(function (req, res) {
// some code
});
Ну то есть вот в такой нотации что не ясно то?
То future() какой-то придумают, чтобы повесить событие и только потом сделать обычный синхронный запрос.
То превратят синхронный в асинхронный, а потом наоборот, запутают всех и сидят типа гении, раз никто не понимает. То какие-то корутины, то еще что-то…
В PHP симуляция потоков все ставит на свои места…
Неужто так сложно относится к процессу многопоточности, как к чтению например данных с сервака?
Кинули запрос, получили ответ, считали ответ, перевели из json-а в данные, работаем с полученными данными.
В PHP не хватает разве что возможности подождать конкретный поток или массив потоков, они там пачкой запускаются ровно столько, сколько нужно, в яваскрипте этой проблемы нет — «деферы» есть.
Согласен, всегда писать на деферах — можно уехать крышей, но сообразить для них обертку и не велосипедить — это мужество нужно.
Как по мне — цирк, блин.
Здравствуйте, могли бы рассказать как вы сохраняйте интероп с java вводя корутины?
Есть ли возможность вызвать suspend function из java?
Как бы например выглядело использование buildSequence в java?
В какой kotlin код транслирует ts2kt такие ts конструкции (intersection types, union types)?
function extend<T, U>(first: T, second: U): T & U {...}
function padLeft(value: string, padding: string | number) {...}
Встречайте Kotlin 1.1: JavaScript, корутины и многое другое