Здравствуйте, Cyberax, Вы писали:
C>>>Я, как программист на Scala, читаю программы на Kotlin вообще сразу A>>а мне вот ключевое слово fun режет глаза. Слишком плотная ассоциация с "удовольствие", прямо каждый раз как натыкаюсь, первая мысль "что за удовольствие? А, function" C>Мне понравилось, наоборот Видимо, из-за опыта с OCaml'ом.
Мне не понравилось, но не из-за ассоциаций с фанатством, а из-за того, что это трата места и непривычно. ОКамл тут не причем. В ОКамле fun используется как ключевое слово для декларации лямбд. У Котлина лябды имеют другой синтаксис (с избыточными, на мой взгляд, скобками), а fun используется для описания функциональных типов, т.е. вместо "->", по сути. Стрелочка авторам не понравилась. Хотя на мой взгляд — зря.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
C>>Мне понравилось, наоборот Видимо, из-за опыта с OCaml'ом. VD>Мне не понравилось, но не из-за ассоциаций с фанатством, а из-за того, что это трата места и непривычно. ОКамл тут не причем. В ОКамле fun используется как ключевое слово для декларации лямбд. У Котлина лябды имеют другой синтаксис (с избыточными, на мой взгляд, скобками), а fun используется для описания функциональных типов, т.е. вместо "->", по сути. Стрелочка авторам не понравилась. Хотя на мой взгляд — зря.
Оператор "стрелочка" у них зарезервирован для анонимных функций: "val doubled = ints.map {it => it * 2}". В принципе, неплохое решение — fun(), сигнатуры и вызовы разделены.
Кстати, я так подумал, что это действительно реально удобно.
Здравствуйте, VladD2, Вы писали:
VD>Справидливости ради надо заметить, что их множественное наследование так же требует ручного разрешения конфликтов. Если в у двух наследников есть один и тот же метод, то нужно его обязательно переопределить.
Но в Скале для этого сделали целый механизм трейтов, с кучей исключений и непоняток. В Котлине, зато, всё тупо и примитивно. А делегирование явно выделено в отдельный паттерн, а не вмешано в трейты.
C>>Case-классы я вообще в принципе ненавижу. Это запредельная кривость. VD>А что ты предлагаешь? Варианты/объеденения как в классихческих ФП?
Мне не нравится явное выделение их в специальную сущность. В Скале они используются для:
1) Специальный случай для классов-значений, с автогенерируемыми hashCode, equals и т.п. Нафиг не надо — должен быть общий механизм.
2) Только для них, по сути, в языке и встроено деструктурирование для PM (ну ещё для списков). Что тоже должно быть доступно для всех классов, в том числе и legacy-бинов.
C>>В Scala PM на практике требует использования case-классов. В Kotlin оно реализовано, как я вижу, через деструктурирующие функции, в том числе для обычных бинов. VD>По-моему ты ошибаешься. В Kotlin точно так же описываются классы с неявным конструктором, что аналогично кейс-классам (вид в профиль). http://confluence.jetbrains.net/display/Kotlin/Pattern+matching Всё что требуется от классов для участия в PM — это иммутабельность. Ну и явная возможность задавать деструктуризатор, тогда как в Scala надо делать case-класс и implicit-конвертор в него.
A>>>Скала у всех на слуху, а взлетает долго. Мне кажется этот ещё дольше будет взлетать. C>>Scala слишком кривая местами. VD>Например?
Управляющие конструкции (в Kotline есть нелокальный return), trait'ы, case class'ы.
C>>Kotlin выглядит как почищенная от мусора Scala. VD>Во многом так оно и есть. В прочем, местами перечистили. Лябды какие-то кривенькие.
Из примера в http://confluence.jetbrains.net/display/Kotlin/Functions :
Это ещё и получше будет, чем в Scala. Особенно учитывая наличие анонимных типов (aka "именованые туплы").
C>>Я, как программист на Scala, читаю программы на Kotlin вообще сразу — всё знакомое. Но при этом ВСЕ мои проблемы в Скале исправлены в Котлине. VD>Дык описал бы эти проблемы и то как они решены в Kotlin.
Частично описал здесь: http://rsdn.ru/forum/philosophy/4349959.aspx
В общем, если эти товарищи сейчас не будут пытаться запихать незапихиваемое, то получится очень неплохой язык. С метапрограммированием лучше подождать, так как слишком уж опасная это штука. Как implicit'ы в Scala.
Здравствуйте, VladD2, Вы писали:
C>>Я, как программист на Scala, читаю программы на Kotlin вообще сразу — всё знакомое. Но при этом ВСЕ мои проблемы в Скале исправлены в Котлине. VD>Дык описал бы эти проблемы и то как они решены в Kotlin.
О! И даже оператор typeinfo есть: http://confluence.jetbrains.net/display/Kotlin/Runtime+Type+Information
Следующий шаг, понятное дело, это Expression Tree внутри typeinfo.
Здравствуйте, Cyberax, Вы писали:
C>Оператор "стрелочка" у них зарезервирован для анонимных функций: "val doubled = ints.map {it => it * 2}".
Ты внимательно на эту стрелочку посмотри. В типах используется "->". В Нмерле для типов используется "->", а "=>" используется для лямбд (=> — это макрос).
Зачем в лябде нужны фигурные скобки я так же понять не могу. В лямбдах каждый символ на счету.
C>В принципе, неплохое решение — fun(), сигнатуры и вызовы разделены.
Где? Ты точно разобрался в синтаксисе?
C>Кстати, я так подумал, что это действительно реально удобно.
Что?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Для дотнетчика (вроде меня) это настолько само собой разумеется, что я не предал этому особого внимания.
C>Следующий шаг, понятное дело, это Expression Tree внутри typeinfo.
Ну, это уже довольно большой шаг. Да и не в том направлении. Лучше бы сделать макросы, а уже все финтифшюшки на их базе.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Cyberax, Вы писали:
C>Здравствуйте, VladD2, Вы писали:
VD>>Справидливости ради надо заметить, что их множественное наследование так же требует ручного разрешения конфликтов. Если в у двух наследников есть один и тот же метод, то нужно его обязательно переопределить. C>Но в Скале для этого сделали целый механизм трейтов, с кучей исключений и непоняток. В Котлине, зато, всё тупо и примитивно. А делегирование явно выделено в отдельный паттерн, а не вмешано в трейты.
Согласен, что для понимания подход Котлин (так и хочется котлетой называть ) лучше. Но чисто технически — это те же самые трейтсы. Просто для них нашли более понятную форуму.
Я именно это и хотел сказать. Идея с эмуляция МН мне очень даже нравится. Единственное, что она не очень вяжется с явой. Интерфейсов то в явном виде нет. У людей могут возникнуть непонятки.
C>>>Case-классы я вообще в принципе ненавижу. Это запредельная кривость. VD>>А что ты предлагаешь? Варианты/объеденения как в классихческих ФП? C>Мне не нравится явное выделение их в специальную сущность. В Скале они используются для: C>1) Специальный случай для классов-значений, с автогенерируемыми hashCode, equals и т.п. Нафиг не надо — должен быть общий механизм. C>2) Только для них, по сути, в языке и встроено деструктурирование для PM (ну ещё для списков). Что тоже должно быть доступно для всех классов, в том числе и legacy-бинов.
Почти уверен, что у Котлина те же ограничения и то же поведение. Ну, разве что hashCode и equals не нужно реализовывать.
C>>>В Scala PM на практике требует использования case-классов. В Kotlin оно реализовано, как я вижу, через деструктурирующие функции, в том числе для обычных бинов. VD>>По-моему ты ошибаешься. В Kotlin точно так же описываются классы с неявным конструктором, что аналогично кейс-классам (вид в профиль). C>http://confluence.jetbrains.net/display/Kotlin/Pattern+matching Всё что требуется от классов для участия в PM — это иммутабельность.
Что-то я там такого не увидел. По-моему, ты что-то путаешь.
Потом я с автором языка общался пару месяцев назад, и он мне четка сказал, что описание берется из определения класса. Вряд ли что-то за это время изменилось.
C>Ну и явная возможность задавать деструктуризатор, тогда как в Scala надо делать case-класс и implicit-конвертор в него.
Какие еще на фиг деструкторы? Это ты про Decomposer functions?
A>>>>Скала у всех на слуху, а взлетает долго. Мне кажется этот ещё дольше будет взлетать. C>>>Scala слишком кривая местами. VD>>Например? C>Управляющие конструкции (в Kotline есть нелокальный return),
Чё? Это ты о инлайн-функциях что ли? Можно пример?
C> trait'ы, case class'ы.
Проблемы то где?
C>>>Kotlin выглядит как почищенная от мусора Scala. VD>>Во многом так оно и есть. В прочем, местами перечистили. Лябды какие-то кривенькие. C>Из примера в http://confluence.jetbrains.net/display/Kotlin/Functions : C>
Можно вбить внятные имена. Нет непонятных скобок. Нет проблем, если параметров у лямбды должно быть несколько.
C>Это ещё и получше будет, чем в Scala. Особенно учитывая наличие анонимных типов (aka "именованые туплы").
Как только речь заходит о случаях которые не укладываются в сахар с it, то все становится не так радужно.
C>>>Я, как программист на Scala, читаю программы на Kotlin вообще сразу — всё знакомое. Но при этом ВСЕ мои проблемы в Скале исправлены в Котлине. VD>>Дык описал бы эти проблемы и то как они решены в Kotlin. C>Частично описал здесь: http://rsdn.ru/forum/philosophy/4349959.aspx
Там описано что тебе понравилось. Но про проблемы ни слова.
C>В общем, если эти товарищи сейчас не будут пытаться запихать незапихиваемое, то получится очень неплохой язык. С метапрограммированием лучше подождать, так как слишком уж опасная это штука. Как implicit'ы в Scala.
Ничего там опасного нет. Это домыслы. Авторы на грани. Мысли есть. Но есть страх неизведанного (как у тебя).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, MasterZiv, Вы писали:
MZ>On 20.07.2011 14:05, Cyberax wrote:
>> Мне этот язык всё больше и больше нравится:
MZ>Как бы не понравится сложно: Java уже давно MZ>плесенью покрылась, и не в один слой. MZ>Что там у них Гай Стил делает -- не понимаю.
Здравствуйте, VladD2, Вы писали:
C>>Оператор "стрелочка" у них зарезервирован для анонимных функций: "val doubled = ints.map {it => it * 2}". VD>Ты внимательно на эту стрелочку посмотри. В типах используется "->". В Нмерле для типов используется "->", а "=>" используется для лямбд (=> — это макрос).
Это не такое уж хорошее решение, тогда.
VD>Зачем в лябде нужны фигурные скобки я так же понять не могу. В лямбдах каждый символ на счету.
Фигурные скобки, наверное, можно опускать. Действует то же правило, что и в Java/C. Впрочем, мелочи.
C>>В принципе, неплохое решение — fun(), сигнатуры и вызовы разделены. VD>Где? Ты точно разобрался в синтаксисе?
Да. Мне в Скале не очень нравится то, что функциональные типы и лямбды описываются с помощью одного и того же символа "=>". Их разделение мне кажется правильным решением.
Здравствуйте, VladD2, Вы писали:
C>>1) Специальный случай для классов-значений, с автогенерируемыми hashCode, equals и т.п. Нафиг не надо — должен быть общий механизм. C>>2) Только для них, по сути, в языке и встроено деструктурирование для PM (ну ещё для списков). Что тоже должно быть доступно для всех классов, в том числе и legacy-бинов. VD>Почти уверен, что у Котлина те же ограничения и то же поведение. Ну, разве что hashCode и equals не нужно реализовывать.
У Котлина как минимум PM по всем иммутабельным типам делается, в том числе и legacy. Генерация hashCode/equals — пока непонятно.
VD>>>По-моему ты ошибаешься. В Kotlin точно так же описываются классы с неявным конструктором, что аналогично кейс-классам (вид в профиль). C>>http://confluence.jetbrains.net/display/Kotlin/Pattern+matching Всё что требуется от классов для участия в PM — это иммутабельность. VD>Что-то я там такого не увидел. По-моему, ты что-то путаешь. VD>Потом я с автором языка общался пару месяцев назад, и он мне четка сказал, что описание берется из определения класса. Вряд ли что-то за это время изменилось.
То есть?
C>>Ну и явная возможность задавать деструктуризатор, тогда как в Scala надо делать case-класс и implicit-конвертор в него. VD>Какие еще на фиг деструкторы? Это ты про Decomposer functions? Деструктуризаторы, не деструкторы — это стандартный термин в PM. Т.е. функции, разбирающие объект на составные части, которые можно использовать в PM.
В Kotlin:
decomposer fun Any?.Tree() : (Tree?, Tree?)?
{
if (this is Tree) return (left=this.left, right=this.right) return null
}
//И дальше спокойно матчим
В Скале:
//Есть класс:class Tree {
val left : Tree;
val right : Tree;
}
//Хочешь PM по этому классу делать? А вот обломись!
//Нужно делать что-то типа:
implicit object TreeWrapper {
def unapply(t : Tree) = {
(t.left, t.right)
}
}
//Теперь можно делать так:
val tr : Tree = ....;
match(tr) {
case TreeWrapper(t) => Console.print(t._1, t._2);
}
//Если хотим вместо неименованых параметров _1, _2
//использовать left и right - то нужно делать отдельный case-class
Стоит ли говорить, что после этого использование PM при работе с legacy-кодом превращается в ужас?
C>>Управляющие конструкции (в Kotline есть нелокальный return), VD>Чё? Это ты о инлайн-функциях что ли? Можно пример?
Ага. http://confluence.jetbrains.net/display/Kotlin/Nonlocal+returns+and+jumps (раздел "Break and continue is custom control structures") — в Скале такое не получается.
VD>И что? А если нужно два параметра? И зачем эти скобки? Сравни Шарп: VD>
VD>from s in strings where s.length == 5 orderby s select s.toUpperCase()
VD>
VD>Можно вбить внятные имена. Нет непонятных скобок. Нет проблем, если параметров у лямбды должно быть несколько.
Различие с Котлином будет только в скобках. По мне — пофиг.
C>>Это ещё и получше будет, чем в Scala. Особенно учитывая наличие анонимных типов (aka "именованые туплы"). VD>Как только речь заходит о случаях которые не укладываются в сахар с it, то все становится не так радужно.
То есть?
C>>Частично описал здесь: http://rsdn.ru/forum/philosophy/4349959.aspx
VD>Там описано что тебе понравилось. Но про проблемы ни слова.
То что понравилось — в Скале неудобно.
C>>В общем, если эти товарищи сейчас не будут пытаться запихать незапихиваемое, то получится очень неплохой язык. С метапрограммированием лучше подождать, так как слишком уж опасная это штука. Как implicit'ы в Scala. VD>Ничего там опасного нет. Это домыслы. Авторы на грани. Мысли есть. Но есть страх неизведанного (как у тебя).
Не, ну про implicit так же говорили. А получился ужастик в итоге.
C>//Есть класс:
C>class Tree {
C> val left : Tree;
C> val right : Tree;
C>}
C>//Хочешь PM по этому классу делать? А вот обломись!
C>//Нужно делать что-то типа:
C>implicit object TreeWrapper {
C> def unapply(t : Tree) = {
C> (t.left, t.right)
C> }
C>}
C>//Теперь можно делать так:
C>val tr : Tree = ....;
C>match(tr) {
C> case TreeWrapper(t) => Console.print(t._1, t._2);
C>}
C>//Если хотим вместо неименованых параметров _1, _2
C>//использовать left и right - то нужно делать отдельный case-class
C>
Это на каком языке код? В Scala
class Test {
class Tree(val left : Tree, val right : Tree)
implicit object TreeWrapper {
def unapply(t : Tree) = Some(t.left, t.right)
}
def main(args: Array[String]) {
val tr : Tree = null;
tr match {
case TreeWrapper(t1, t2) => println(t1, t2);
}
}
}
прекрасно работает.
C>Стоит ли говорить, что после этого использование PM при работе с legacy-кодом превращается в ужас?
Ну ужас. Но не ужас-ужас-ужас. Ведь есть RichXXX, плюс, как видно экстракторы лишь на строчку длинее декомпозера.
C>>>Управляющие конструкции (в Kotline есть нелокальный return), VD>>Чё? Это ты о инлайн-функциях что ли? Можно пример? C>Ага. http://confluence.jetbrains.net/display/Kotlin/Nonlocal+returns+and+jumps (раздел "Break and continue is custom control structures") — в Скале такое не получается.
Отчего же? Есть scala.util.control.Break
C>Не, ну про implicit так же говорили. А получился ужастик в итоге.
Здравствуйте, Cyberax, Вы писали:
C>3) Null-safety вмонтировано в язык. В Скале только уродский Option, который даже для Pattern matching'а использовать нормально нельзя.
Есть NotNull, но его ещё не допилили до человеческого состояния. И это nullable по умолчанию, а не notnull.
Почему Option уродский? Почему нельзя нормально использовать для паттерн-матчинга?
C>7) Именованные параметры, в том числе для туплов.
Здравствуйте, avpavlov, Вы писали:
A>Сайберакс имеет ввиду что названия .left .right мы потеряли, и нужно вводить свои (t1,t2) или пользоваться анонимными ._1/._2
Не понимаю. Можно показать, где именно потеряли?
Ведь можно и так:
case tree @ TreeWrapper(left, right) =>
и у нас связаны три переменные tree: Tree и left, right.
A>На самом деле нет ни одной причины не объявить Tree как case class. Так что на мой взгляд он просто привередничает
Варианты в Nemerle кажутся синтаксически удобнее, правда, не знаю, можно ли их расширять. Что касается сравнения Scala vs Kotlin соглашусь, разница незначительна.
Здравствуйте, avpavlov, Вы писали:
M>>Ведь можно и так:
M>>
M>>case tree @ TreeWrapper(left, right) =>
M>>
A>Но это уже на совести программиста
Во-первых, та же Идея подсказывает имена по Ctrl-P в экстракторах,
во-вторых, есть случаи, когда хочется дать другие имена.
В теории практика не отличается от теории, но на практике — отличается