Pull to refresh

Comments 119

А Clay действительно интересный, несмотря на квест по поиску доки
Что-то не понятно в чем интрига то, ясен пень, что Хаскел лучший. Сто раз обсуждалось уже…
Вы отстали от жизни. Пару недель назад нам доказали, что лучший — оберон.
Я предлагаю делать ставки. Ясен пень, что манной небесной окажется что-то из неупомянутого. Эрланг?
Конечно, Erlang — это замечательный язык, но он вроде не компилится в js. Или я отстал от жизни уже? Мне, лично, никогда это не требовалось, чтобы что-то компилировалось в js.
Beam написан на Си, его всегда можно жахнуть emscripten'ом
Есть подозрение, что это будет ужасающе.
UFO just landed and posted this here
Это ж Платов, его идеальный язык — Fantom. На нём весь Xored пишет (ну или почти).
Xored, кстати, не пишет «в основном» на Fantom. У них там, насколько я понимаю, Java-кода больше всего. Могу ошибаться, конечно, только Fantom не на первом месте по кодобазе — инсайдерская инфа.
Вполне возможно, просто в вакансиях Xored обычно пишется «Нам пофиг, на чём вы пишите, вам придётся изучать Fantom»…
Это маркетинг. Они, действительно, хайрят просто умных и хороших разработчиков вне плоскости какой-либо технологии. А Fantom упоминают для красного словца. Ну хотя есть небольшой шанс, что таки попадешь на проект с Fantom'ом. Я не в курсе, может, у них такие все еще живут, — тут только Андрей может рассказать.
Это просто старая вакансия, да, когда то был план сделать Fantom основным языком, но не сложилось. Я не интересовался обновляют ли или нет эту вакансию.
Я думаю автор плавно подведет нас к ассемблеру.
Сомневаюсь, в 1 части автор писал
Да, да, еще три дня назад я и не думал что единороги существуют — ведь каждый язык так или иначе сосет, и каждый сосет по-своему (хотя нет, есть и такие которые сосут всегда и везде, но о них не будем).


не думаю что про asm он узнал 3 дня назад.
Мой коммент был тонким сарказмом.
Может Rust?
Он недавно зарелизился, а автор вроде как подводит, он недавно нашел идеальный язык…
UFO just landed and posted this here
Говорил, в середине последнего абзаца предыдущей части.
Ставлю на Swift. Apple сказала, что откроет его, а тут и статья. Совпадение? :)
А есть какие нибудь материалы по теме? Интересно было бы ознакомиться.
Та все поняно… про Nim тут разных местах стал слышать восторженные возгласы.
Автор походу из того же лагеря.
Надеюсь только он безо всяких молебен расскажет в чем цимус, и почему Nim.
Я так понимаю, что выбор стоял между Dart и TypeScript?
пареллелизма в них нет настоящего.
На мой взгляд dart:isolate обеспечивает самые что ни на есть параллельные вычисления (пускай и без разделения по памяти), c фолбеком для браузеров через Web Workers.
Только вот запустить и передать данные в изолят накладнее, чем в другой процесс ОС.
кому не терпится узнать что за язык такой — посмотрите в твиттере автора)
Я опять что-то в жизни упустил. Вот жил себе жил, были C, C++, Delphi, VB, Pascal, PHP. А потом раз, 2015 год — и куча, неет, КУУУУЧА новых непонятных слов. Откуда? Что это? Зачем?
Тут еще все достаточно консервативно. C++ как был так и остался, Delphi и PHP в общем тоже. У M$ в 2000-х была мода на разные аббревиатуры, но сейчас такое впечатление что поуспокоились.
Сейча самый ад — веб-фреймворки. Тысячи их, и даже если захочешь изучить что-то — пока думаешь что изучать еще десяток появится.
Каждый год появляется по одному-двум новым и лучшим языкам программирования. Это нормально, обычный круговорот мозгов: студент — аспирант (новый лучший язык) — доктор наук.
Ох, ну сколько можно. вы никогда не получите на статической типизации такой скорости разработки, как на языках с динамической типизацией, и наоборот про производительность. про инфраструктуру и сообщество я уже молчу.
Влепил автору заслуженный минус за троллинг.
Еще вы никогда не получите такого количества ошибок типизации. Проекты среднего и больше размера лучше писать на статически типизированных языках, иначе рефакторинг превращается в ад и Израиль.
ещё один человек с субъективом «я не умею динамическую типизацию, поэтому она хуже»
Научите? Правда, очень хочется. Я на работе пишу на Ruby, и сильно страдаю от динамической типизации. Немного помогают аннотации, хорошо помогают тесты, но все равно случаются ошибки в production'е. Автор, кстати, тоже не умеет.

… динамическая типизация мне не интересна. Это все для людей с большим модулем памяти в башке.

UFO just landed and posted this here
Undefined method method_name on class_name, очевидно. Чаще всего это NilClass.
вызов метода у нуля — частая ошибка новичка и в ruby, и в js. вы, в общем-то, подтвердили мои слова про «не умею динамическую типизацию».
моё время не настолько дешёвое, чтобы я начал рыться на гитхабе в С++ — проектах, чтобы выдать списком issues, где появляются внезапные утечки памяти и переполнения стека от простой смены компилятора.
олсо, как минимум в одном ошибка выпадает из-за биндинга БД, написанного на ЯП со статической типизацией.
Null reference не падает только у тех, кто обмазывает код контрактами (с проверкой времени компиляцией), или у тех у кого в языке есть статическая типизация + явное разделение на nullable и non nullable сущности (aka Option).
Да блять, у программера средней руки падает NullReference вне зависимости от типа типизации его языка. Только в рамках динамически типизированного языка нельзя сделать явное разделение на nullable/non-nullable сущности.
UFO just landed and posted this here
вы тупо всё время на устранение ошибок, которые могут возникнуть в продакшене, тратите на устранение compile-time ошибок при статической типизации. это раз.
ошибки, связанные с типизацией в продакшене обычно возникают на непокрытой тестами среде. опечатки и прочий хлам. это качество вашего кода и процесса разработки, а не проблема типизации в целом, это два.
автор не говорил, что не умеет. он указал на аппетиты по памяти. это три.
Хорошо, давайте разберем.
1. Устранить ошибку на ранних этапах разработки дешевле, согласны? Чтобы починить в production'e нужно исправить, пройти code review, тесты, и задеплоить (возможно у вас есть еще этапы). А чтобы исправить падающую программу нужен только первый этап.
2. Ошибка исправленная на раннем этапе не вредит пользователям.
3. Все люди ошибаются. Компиляторы внимательны. Статическая типизация позволяет избежать этого класса ошибок раз и насовсем. Я согласен, что это проблема людей, но, мне кажется, лучше использовать компилятор, чем вживлять себе ген слона, чтобы все помнить.

Я думаю, автор имел ввиду, что у него не получается держать в памяти (которая в голове) всю необходимую информацию, чтобы хорошо писать на динамически типизированных языках.
в вашем фундаменте есть одна большая прореха. вы считаете, что ошибки языков со статической типизацией не доходят до пользователя. это заведомо неверно. они гораздо труднее отлавливаются, и приносят не меньше проблем. могу для начала привести пример с переполнением стека.
ну и да, в нормальном процессе code review и тесты — это часть программирования, а не мера после нахождения ошибки в продакшене.
я подозреваю, что вы — просто один из тех людей, которых скорость разработки на ЯП с динамической типизацией извратила до патчей без тестирования в продакшн. отсюда и столько негатива. ну или вы просто часто сталкиваетесь с такими людьми в работе.
Нет, я так не считаю. Есть разные классы ошибок. Переполнение stack'a — отдельный класс, который, есть и в динамических языках. Он вообще никак не связан с типизацией. Так же, как не связаны с типизацией утечки памяти. Я считаю, что статическая типизация позволяет отсеять все ошибки типизации, особенно если в вашем языке нет ошибки на миллиард долларов.

Проблема с тестами в том, что невозможно проверить все возможные варианты входных данных.
ах да. похлопаем. null-reference mistake — это ошибка, родившаяся в языках со статической типизацией.
олсо, переполнение стека в ЯП с динамической типизацией возможно только в бесконечной рекурсии и приводит к «Exception: stack overflow». и именно в ЯП со статической типизацией оно может случиться от любого неаккуратного обращения с памятью, и приводит к чему угодно, вплоть до выполнения случайного кода.
и именно в ЯП со статической типизацией оно может случиться от любого неаккуратного обращения с памятью, и приводит к чему угодно, вплоть до выполнения случайного кода

Вам 70ые звонили, просили книгу K&R вернуть.
пощади, чилавек-онегдот!
кроме скалы и джавы, ещё существуют ЯП, кстати.
На динамически типизированных языках совершенно невозможно делать нормальный concurrency. Какая может быть memory model у языка, где у любого объекта может быть абсолютно любой набор свойств, которые можно добавлять/убирать в рантайме? Делать всё volatile по умолчанию? Напоремся на дичайшие тормоза (ещё большие, чем на одном ядре) за счёт постоянной необходимости синхронизации между ядрами.

Ну и, кстати, написать парсер с помощью имеющегося генератора — три часа работы профессионала. Написать интепретатор из AST — ещё пара часов. Написать нормальную систему типов, с generics, closures и хотя бы притивным type inference, да ещё и внятной диагностикой ошибок — приличный объём работы, и немалые познания в некоторых областях computer science. Такое ощущение, что некоторые популярные ныне ЯП с динамической типизацией стали таковыми потому, что авторы просто ниасилили систему типов.
Про concurrency расскажите Эрлангу.
Ага, всегда copy-by-value в чужую кучу. Плюс строгая типизация. То, что она динамическая (один биндинг может в разное время иметь привязку к значению разных типов) уже не так важно.
Ну у Erlang немного специфический concurrency. Акторы рулят не во всех задачах. А главное — на классической многопоточности с примитивами синхронизации можно написать и акторы и STM, а вот наоборот — ну с очень большим трудом (если вообще возможно).
перед тем как возмущаться про concurrency, перечитайте мой коммент выше, особенно его часть про производительность
p.s.: про «ниасилили» систему типов — поржал. миксины, метапрограммирование и рефлексия.
Не понял про миксины, метапрограммирование и рефлексию. Можно бесконечно перечислять фичи языка, и так же бесконечно вводить эти фичи в язык и, соответственно, реализовывать. Вот то, что я назвал — это всего лишь фичи 8-й Java. И даже такую «примитивную» систему типов не так уж просто корректно реализовать. Моя личная практика показывает, что где-то процентов 80 времени тратится на семантический анализатор, с корректным восстановлением после ошибок, который генерит вменяемую диагностику, но при этом не спамит разработчика мусорными сообщениями. Остальное — это парсер и кодогенератор. Первый вообще пишется автоматом каким-нибудь ANTLR-ом. Второй проще реюзать (например, JVM или LLVM), чем изобрести самому, а генерация промежуточного представления — вообще очень простая задача. И даже в отсутствии нормального кодогенератора можно достаточно быстро написать свой тупой (и медленный) в качестве прототипа. А вот на семантическом анализе просто так не срежешь углы. Кроме того, там достаточно много нюансов, в отличие от того же кодогенератора/интерпретатора, которые можно реализовывать интуитивно, без знания матчасти.
вы начали перекидываться «фичами» языка, которые «трудно реализовать» — я вам ответил такими же, свойственными для динамической типизации.
серьёзно, вы смотрите с одной колокольни, и судите только по той точке зрения, что по вашему опыту тяжело было реализовывать в статической типизации. а вот с динамической, у вас, судя по всему, серьёзного опыта просто не было.
А с каких пор миксины, метапрограммирование и рефлексия являются фичами динамически типизированных ЯП? Более того, с каких пор рефлексия является свойством компилятора, а не рантайма? И с каких пор она сложно реализуется?
> А с каких пор миксины, метапрограммирование и рефлексия являются фичами динамически типизированных ЯП
ЯП со статической типизацией не умеют миксины практически все.
метапрограммирование и рефлексию не умеет большинство. Те, кто умеет, делают это неудобно, и с проблемами в безопасности.
> с каких пор рефлексия является свойством компилятора
а с каких пор ЯП характеризуется только компилятором?
> с каких пор она сложно реализуется
а с каких пор просто?
За троллинг ему надо было влеплять заслуженный плюс.
А можно раскрыть подробнее — в чем быстрее скорость разработки?
очевидно же, н нужно тип перед переменной писать…
  1. Система типов мейнстримных языков ущербна чуть более чем полностью. Если у вас в языке есть generics, то скорее всего у вас нету возможности сделать перегрузку метода по generics. И скорее всего нельзя наложить какое-нибудь ограничение вида: TCollection: Collection<TItem>. Это доставляет проблемы.
  2. Отсутствие миксинов и вообще сколь-нибудь адекватной модели ООП приводит к тому, что рождается куча копипасты.
  3. В большинстве мейнстримных языков создание класса — это долгая операция, приводящая к новому файлу и куче говнострок кода. А большинство классов являются тупыми data classes, либо вообще анонимными классами внутри определенного метода.
  4. В большинстве мейнстримных языков нету Type Providers и макросов. Это значит, что ты в любом случае описываешь свои модели. И если у тебя три статически типизированных языка, то ты вынужденно делаешь копипасту классов/таблиц из одного языка в друой. Хотя твой компьютер достаточно умен, чтобы классы автогенерировать и делать статическую проверку по автогенерированному коду, но недостаточно умен, чтобы совместить эти два процесса в один.
  5. Многие практики ынтырпрайз программирования возводят все проблемы в квадрат. Это претензия к ынтыпрайзу. Но все же, дай в руки идиоту ружье — он себе яйца отстрелит.


Соответственно на мелких проектах рулит динамическая типизация, на больших проектах статическая типизация. Оба лагеря срутся и не понимают друг друга. На средних проектах выбор между динамической/статической типизацей основывается на коэффициенте уебищности знакомых языков в данной нише.
P.S: размер проекта зависит от языка, на которым ты пишешь. Если у динамически типизированного языка адекватные фичи и крутой набор библиотек, то количество кода резко уменьшается в раза 3-20 и проект переходит из большого в мелкий.
Алсо если обладать хорошими скиллами проектировки, то проект бьется на несколько проектов с хорошо оттестированными связующими звенами. И вуаля, проект переходит из большого в несколько мелких.

В общем выбор между динамической и статической типизацией сводится к учету готовности:
  • насколько ты готов мириться с фактом, что компилятор тебе не поможет, когда ты поломаешь код
  • насколько ты готов мириться с фактом, что компилятор усложнит тебе работу в n раз
1, 2, 3, 4 — см scala.
5 — ынтерпрайз на JavaScript ничуть не менее кровав, чем на Java.
Ну давай я тоже начну перечислять языки, в которых есть эти фичи. Или ты думаешь я из головы их придумал? Есть один момент: языки, в которых есть эти фичи — это не мейнстрим. И скала не мейнстрим. И эти фишки еще долго не станут мейнстримом. Они еще сырые.

Почему так? Хорошая корректная система типов + автовывод типов + type providers + автокомплит + учет того, что люди работают с системой контроля версий (а значит внезапно может поменять овердохуя файлов) + обеспечение приличной скорости работы и низкого уровня потребляемой оперативной памяти — это адски сложная задача. Вы таки уверены, что в вашем любимом языке учли последние два пункта?

По поводу той же скалы. «Не читал, но осуждаю». Если быть точнее, то я «изучал, но не писал». В языке овердохуя фич. И я это мнение составил до прочтения этой статьи. А некоторые сигнатуры могут привести в обморок новичка или в экстаз копрофила. Пропадает самоочевидность и самодокументируемость статически типизированного кода — ну и нафига оно надо?

Касательно Javascript. Любой проект на Javascript кровав и ужасен. Это связано с тем, что в нем допустима интересная мощная неконтролируемая магия (можно усложнить всем жизнь в разы). Он динамически типизирован, но ни язык, ни сообщество не предлагают ничего, что может сократить количество строк кода в разы. Т.е. никакого профита, одни недостатки.
Если уж на то пошло, то мейнмтрим — это Java, JavaScript, C# и PHP. Все остальное легко записать в немейнстрим.

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

Раз уж вы упомянули автокомплит, то напомню, что он влияет на скорость разработки и при этом невозможен при динамической типизации. В то, что есть, без слез не взглянешь (по опыту js и ror).

Кстати, вы упомянули миксины, но можно еще вспомнить monkey patch в динамических ЯП, который глобален и от того совершенно неюзабелен. Аналогичные механизмы в C# и scala сильно упрощают работу и при этом локальны (extension methods).

Вы сами требуете фичи и при этом обвиняете скалу в их наличии? На мой взгляд в скале как раз не так уж много языковых фич, просто они ортогональны и универсальны, так что могут применяться в различных сочетаниях.
Писать же страшные сигнатуры вас никто не заставляет. В стандартной же библиотеке я помню громоздкие сигнатуры только в случае CanBuildFrom.
Во-первых, я поклонник статической типизации.
Я рассказывал, что таких-то фич может не хватать и исходя из этого языки с динамической типизацией могут быть продуктивнее для девелопера. И разработка этих фич дело весьма сложное и существующие реализации далеко не самые лучшие и уж точно не проверенные опытом. Поэтому опять же возможно ситуация, когда ты больше борешься с языком/средой разработки; а не разрабатываешь как должно быть.

В массовом сознании статическая типизация ассоциируется с Java/C#, а динамическая типизация с JavaScript/PHP. Исходя из этого появляется мысля, что на языках с динамической типизацией писать проще и быстрее, потому что другие языки мешают. Я просто рассказываю, почему такие мысли появляются в головах людей )
>Сразу было понятно что мне нужны Type Classes
Не понятно для чего вам были нужны type classes, но shapeless — это зависимые типы,
type classes это simulacrum или scalaz
но shapeless — это зависимые типы,

Которых в Scala нет на уровне языка, естественно попытка их добавить вылилась в черт знает что. Причем даже в Haskell нет зависимых типов.
Из языков общего назначения, известных мне у которых я знаю названия, они есть только в ATS и Idris.

Я хочу кросс-платформенность с обязательной компиляцией в JavaScript.

Нет. Не может быть. Ну точно не может быть. Это же....Javascript!
Если бы в Delph были макросы, и генерики
Братуха, генерики уже есть, давно!
Может быть это язык D? Он пока в статье не упоминался. С другой стороны не нужно тратить 7 лет, чтобы найти D…
Кто-то написал в комментариях, что ответ есть в Твиттере автора — специально не буду смотреть, жду третью часть!
Предыдущая статья
Так что и Scala я для себя открыл, за годы до того как она появилась в резюмах и головах кандидатов приходящих на собеседование, а некоторые из вас еще в школе учились.


Эта статья
Сразу скажу знаний Scala и опыта у меня близко к нулю, что я компенсирую знаниями и опытом по-жизни


image
Ну может, открыл, выругался и сразу закрыл.
Кстати, я в основном программирую на PHP. Какое-то время назад заинтересовался Clojure, посмотрел лекции Рича Хикки, купил книжечку, читаю (люблю сначала толстую книжку прочитать). И тут в статье:
Вердикт: Clojure — функциональный PHP.
Получается в правильном направлении двигаюсь :)
Ага, у них общего как раз примерно столько же сколько у php и haskell.
Сразу скажу знаний Scala и опыта у меня близко к нулю, что я компенсирую знаниями и опытом по-жизни. Сразу было понятно что мне нужны Type Classes, ну и я давай глядеть в Интернет. Сразу натыкаюсь на некую, да простят меня фанаты Scala, либу shapeless, от Miles Sabin.


Я один из разработчиков компилятора и языка Scala, вы посмотрели не в ту сторону — shapeless и type classes это не то, что вообще рекомендовано к использованию на Scala.

Я конечно глубоко не вникал, может этот shapeless на который надо убить тучу времени (и который видимо далеко не самая навороченная библиотека Scala мира) делает что то там еще полезное, но у меня нет слов — люди делают про это какие-то толки на конфах, воркшопы, презы на 56 страниц типа Demystifying Shapeless. И все это зачем? Чтобы выковырять тип значения во время компиляции, братан.


Вы сделали ровно теже выводы что и мы. Просто не используйте shapeless. Он является скажем так «радикальной» частью сообщества, с которой многие не согласны.
Все что он делает можно реализовать лучше, и сделано уже в сообществе. Например HLists и HMaps намного лучше(и по API и по производительности) реализованы в scala records.
это не то, что вообще рекомендовано к использованию на Scala

Весьма странное заявление, особенно про классы типов.

Все что он делает можно реализовать лучше, и сделано уже в сообществе. Например HLists и HMaps намного лучше(и по API и по производительности) реализованы в scala records.


Это заявление очень далеко от реальности. Максимум, на что тянет scala-records — это реализация части функциональности, связанной с record'ами, которые в shapeless представляются в виде HList'а от специального вида пар. Вероятно, для своей области применения scala-records и удобнее, чем shapeless (как частно бывает, что специализированные инструменты удобнее общих), но говорить, что оно полностью заменяет и лучше чем shapeless в целом — это просто троллинг.
Весьма странное заявление, особенно про классы типов.


Я вам скажу вот что, если бы они были хороши, вы бы нашли их в стандатной библиотеке и они бы были использованы в компиляторе. Либо в старом — scalac, либо в новом — dotty.

Это заявление очень далеко от реальности. Максимум, на что тянет scala-records — это реализация части функциональности, связанной с record'ами, которые в shapeless представляются в виде HList'а от специального вида пар.

но говорить, что оно полностью заменяет и лучше чем shapeless в целом — это просто троллинг.


Я этого и не говорил.
Я НЕ говорил что scala-records реализует все в shapeless. Я сказал, что для конкретной задачи в scala-сообществе есть лучше решения чем shapeless. В частности,
Например HLists и HMaps намного лучше(и по API и по производительности) реализованы в scala records
.
Я вам скажу вот что, если бы они были хороши, вы бы нашли их в стандатной библиотеке и они бы были использованы в компиляторе. Либо в старом — scalac, либо в новом — dotty.

Они есть в стандартной библиотеке, только мало (например, Numeric или Ordering или ClassTag/TypeTag). Стандартная библиотека связана гарантиями обратной совместимости, и поэтому добавлять туда что-то новое очень трудно. Классы типов в языке возникли сами по себе, на основе имплиситов, и именно поэтому они не используются широко в стандартной библиотеке — когда она создавалась, про них и не думали. Тем не менее, когда их «открыли», соответствующие фичи были добавлены прямо в язык (context bounds же).

В «старом» компиляторе много легаси-кода, который никто не будет переписывать, даже если в этом и есть нужда. Я слабо разбираюсь в компиляторостроении, но далеко не факт, что абстракция классов типов нужна при разработке компилятора, и это может быть объяснением того, что в dotty они не используются.

Также хочу привести в пример scala-pickling, который является официальным проектом Scala, который целиком основан на классах типов и который, насколько я в курсе, хотят применить или уже применяют в компиляторе.

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

Я этого и не говорил.

Например HLists и HMaps намного лучше(и по API и по производительности) реализованы в scala records

Да, возможно я немного преувеличил про «всё», но и вы, мягко говоря, преувеличиваете про HList и HMap. Как я уже сказал, в scala-records ими и близко не пахнет.
Стандартная библиотека связана гарантиями обратной совместимости, и поэтому добавлять туда что-то новое очень трудно. Классы типов в языке возникли сами по себе, на основе имплиситов, и именно поэтому они не используются широко в стандартной библиотеке — когда она создавалась, про них и не думали.


Я не хочу вас расстраивать, но у вас явно ложное впечатление о Scala и ее истории.
Вопервых, в scala 2.8 была сломана вся обратная совместимость. И половина стандартной библиотеки использует implicits, с тех пор. Про это все думали, и до этого были views которые решали подобную задачу.

Я слабо разбираюсь в компиляторостроении, но далеко не факт, что абстракция классов типов нужна при разработке компилятора, и это может быть объяснением того, что в dotty они не используются.

Вы спорите с разработчиком dotty. Мы их используем, наоборот, мы НЕ используем cake pattern как старый компилятор, те — у нас почти все — классы.

Также хочу привести в пример scala-pickling, который является официальным проектом Scala, который целиком основан на классах типов и который, насколько я в курсе, хотят применить или уже применяют в компиляторе.

Вы не в курсе. Его не применяют и планов нет. Есть планы юзать в Spark. Самая новая сериализация в Dotty — TASTY не имеет ничего общего с pickling.

Прошу вас, перед тем как убеждать людей, проверяйте ваши аргументы. Вы ваши предположения преподносите как истину.

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


Вот это я и говорю, что shapeless это то, что разработчики компилятора и стандартной библиотеки, советуют НЕ использовать для чего-либо более чем простых примеров, если вам важна производительность, легкость понимания что код делает, бинарная совместимость.
Мы их используем, наоборот, мы НЕ используем cake pattern как старый компилятор, те — у нас почти все — классы.

Это не противоречит вашему заявлению о том, что классы типов не рекомендуются? И про cake pattern здесь вообще ни слова не было, это совершенно отдельная тема.

Views, кстати, это совсем не то же, что классы типов, по своей семантике.

Его не применяют и планов нет

По крайней мере, про это было сказано в презентации про scala-pickling здесь (страница 55):
Experiment: use Scala-pickling to speed up Scala compiler


Вот это я и говорю, что shapeless это то, что разработчики компилятора и стандартной библиотеки, советуют НЕ использовать


shapeless — может быть, классы типов — сильно сомневаюсь.

Насчёт всего остального — признаю свою ошибку, был не прав.
Простите, но Typesafe пропихивают Slick который чуть менее чем полностью сделан из Shapeless…
Подозреваю, что покормлю тролля, но всё же хочется «принести свет истины». Я хочу возразить по поводу shapeless и вашего превратного восприятия того, зачем эта библиотека нужна, что она делает и как устроена.

В первую очередь, я вынужден признать, что, к сожалению, нормальной документации по shapeless действительно мало. Я не знаю, с чем это связано, но это действительно так, и полного обзора фич shapeless, насколько я знаю, не существует. Здесь вы правы.

Во-вторых, shapeless и тайпклассы связаны примерно так же, как библиотека коллекций (любая, на ваш выбор) и дженерики. shapeless — это всего лишь библиотека, которая основана на тайпклассах. Но сами тайпклассы, как особенность языка, от shapeless совершенно не зависит. Вы свободно можете писать свои классы типов без всяких сторонних библиотек. shapeless нужен для облегчения определённого класса задач, и в своих областях он справляется великолепно. И, соответственно, наоборот — аналог shapeless и его ключевых элементов вроде HList можно реализовать на любом языке, в котором есть необходимые фичи.

Далее,
Чувак убил годы на то, чтобы люди убивали недели и месяцы чтобы сука сослаться на тип, и понять тип значения в рантайме

Бебать, да я в 95 программировал на Delpi и у меня все это сразу было. Я ничего не знал про Polymorphic typed λ-calculus, да и сейчас ничего не знаю, но вот цимус в том что и без знаний любой школьник на дельфи, напишет такой HList за 10 минут, и тип в рантайме познает, и сошлется на него, и сравнит и хрен знает что еще.


Вполне очевидно, что вы не поняли, о чём вообще здесь речь и не пожелали разбираться дальше. Хотя бы потому, что «понять тип значения в рантайме» (что, строго говоря, делается с помощью отражения и совершенно не связано с какими-либо библиотеками) — это диаметрально противоположная задача от той, которую выполняет HList. Я очень сильно сомневаюсь, что на дельфи можно написать HList, потому что система типов в дельфи недостаточно мощная для этого, причём в математическом смысле, а не в каком-то абстрактном. Даже если это и можно сделать (как минимум, для этого понадобятся дженерики — версиях дельфи, которые были в 95-м, их вроде бы не было), то сами по себе гетерогенные списки бесполезны — в них важен тот набор операций, который над ними можно осуществлять. А эти операции без продвинутых языковых фич (вроде тех же тайпклассов) описать практически невозможно.

Вы, вероятно, знаете, что такое кортеж (не в смысле Python, а в смысле статически типизированных языков, или, ещё точнее, математики). Это структура данных, содержащая фиксированное количество элементов потенциально различного типа:
val x: (Int, String) = (1, "hello")
println(x._1)
println(x._2)


В типе кортежа указывается, какие типы и в каком порядке могут в нём содержаться, соответственно, (Int, String) != (String, Int).

Гетерогенный список (HList) эквивалентен (изоморфен) кортежу. Абсолютно всё, что возможно сделать с помощью кортежей, можно сделать с помощью HList'ов, и наоборот.
val x: Int :: String :: HNil = 1 :: "hello" :: HNil
println(x.head)
println(x.tail.head)


Однако представление кортежа в виде гетерогенного списка гораздо удобнее при описании операций над ним. Вот здесь приведён список операций, который можно осуществлять над разными гетерогенными структурами, в частности, над HList.

Оставим в стороне вопрос о том, зачем это всё нужно, например, зачем нужны все эти операции. Я могу сказать, что это действительно нужно в определённых областях (например, при создании типобезопасной сериализации или при типобезопасной работе с базами данных), но про это можно рассказывать очень долго. Если вам действительно интересно, то вы можете посмотреть примеры использования shapeless. Я хочу сказать, что вот это:
object IsHCons1 {
  type Aux[L[_], FH[_[_]], FT[_[_]], H0[_], T0[_] <: HList] = IsHCons1[L, FH, FT] { type H[t] = H0[t] ; type T[t] = T0[t] }
  def apply[L[_], FH[_[_]], FT[_[_]]](implicit tc: IsHCons1[L, FH, FT]): Aux[L, FH, FT, tc.H, tc.T] = tc
  implicit def mkIsHCons1[L[_], FH[_[_]], FT[_[_]]]: IsHCons1[L, FH, FT] = macro IsHCons1Macros.mkIsHCons1Impl[L, FH, FT]
}

как ни странно, не предполагается писать пользователям библиотеки. Да, «кишки» shapeless довольно сложны. Однако тем, кто использует её, в большинстве случаев погружаться в них не нужно. Поэтому да, такое вас никто не заставляет «писать каждый день сотнями строк».

Да, Scala — это сложный язык, предоставляющий множество абстракций и имеющий свои «болезни», некоторые из которых довольно неприятные. Но вас никто не заставляет использовать все эти абстракции сразу и целиком. Вот здесь есть хорошее описание «уровней» языковых фич. Если вам не нужно программирование на типах — ок, просто не используйте его и не используйте библиотеки, которые на нём основаны. То же самое с макросами, структурными типами и прочим. Как широко говорилось, вы можете писать на Scala как на Java. Однако некоторые вещи, такие как те же гетерогенные списки (которые, кстати, впервые были сделаны не в Scala, а очень даже в Haskell, если не раньше), сами по себе являются сложными вне зависимости от языка, на котором они сделаны. Поэтому говорить, что язык плохой, потому что на нём, дескать, можно написать сложные библиотеки, по меньшей мере неправильно.
Отличный ответ!

Добавлю свои пять копеек. Shapeless — это скорее библиотека не для конечного пользователя а для разработчиков библиотек. Shapeless помогает атворам библиотек избавиться от boilerplate кода и макросов при решении типичных задач. Задач №1, с которой успешно справляется HList: у вас есть два типа A и B как их собрать в месте во что-то с чем вы можете потом работать. Можно собрать из них Scala tuple (A, B) и этого бывает достаточно в большинстве случаев, но когда речь идет о трех, четырех, и тд типов — появляются nested tuples (A, (B, (C, D))) с которыми уже не очень удобно работать как автору библиотек так и ее пользователю. Эта проблема частично решается с помощью некоторго количества boilerplate кода который нужно поддерживать и тестировать. Идея Shapeless (HList в честности) — это как раз дать разработчикам библиотек единый инструмент для решения этой проблемы. Т.е. boilerplate код о которым мы говорили ранее — переносится в Shapeless а значит нам его уже поддерживать не надо.

Еще одна очень интересная особенность Shapeless. При правильном ее использовании автором библиотеки, ее пользователи никогда не догадаются что там где-то в недрах привычного API трудится HList. Примерами таких удачных внедрений я могу назвать scodec, Spray, parboiled2.

На последок, есть отличная презентация от Трэвиса Брауна (#1 Shapeless эксперт на SO) о том как и почему Shapeless был внедрен в Finch.
Кстати. Вот пример того как на Shapeless решена задача о башнях Ханое. Что такого? — Скажете вы. А вот что — задача решается пока программа компилируется. Те. Scala компилятор решает ее за вас до того как вы запускаете эту программу!
Да, так и есть, хотя с непривычки (да и не только с непривычки, если честно) программа выглядит страшно :)

К сожалению, Scala, хоть и имеет очень мощную систему типов, не затачивалась на подобные вычисления на этапе компиляции. Например, появляются сторонние костыли попытки улучшения вроде такого. Поэтому выглядит это всё, без преувеличения, ужасно. Тем не менее, причины использовать подобное есть, и довольно весомые.
Мне больше нравится в этом плане агда. Там можно сделать то же, но не используя метаязык, который выглядит сильно иначе, а используя обычную агду. А HList напоминает шаблонное метапрограммирование на си++
Вы еще HAXE не пробовали, можт срастется :)

Тоже когда-то блуждал в поисках идеального языка, но работа заставляет возвращаться в Java. По экосистеме и количеству проектов у Java нынче нет конкурентов, и близко не предвидится. Поэтому приходится выбирать что-то JVM-совместимое, желательно как можно ближе к Java. Свой быдлокод часто пишу на Groovy, чтобы было меньше мусора. Посматриваю в сторону Kotlin-а, но тот не вылезает из вечной альфы. Пробовал Xtend, но выигрыш сомнительный. Fantom не имеет и никогда не будет иметь generics. Ceylon имеет несколько интересных концепций, но на кой-то черт создатели переименовали все привычные ключевые слова на свой лад. К Scala сразу появилось отвращение: это ужасный неэстетичный монстр, напичканный нечитабельными значками. Как показал человек выше: «Вам не надо шарить в кишках, мы вам дадим сборник рецептов и магических заклинаний как это можно использовать».

И тем не менее, все современные языки похожи. Каждый последующий пытается вписать в себя все предыдущие концепции плюс добавить еще какую-то модную вещицу. И практически никто не пытается переосмыслить многие вещи и выкинуть лишнее. Похоже основной целью у всех является, чтобы можно короче написать. Для меня в первую очередь самое необходимое в языке — это возможность моделировать данные и интерфейсы и организовывать их соответствующим образом. Java Beans — худшее, что можно представить для моделирования данных.
Андрей, ну раз так долго искал свой идеал, и знал как он _должен_ выглядеть, почему ты просто не реализовал свою мечту? (Слово «просто» может и не к месту в данном контексте :) )
Даже если оставить в стороне вопрос денег, времени и возможностей, если начать пилить язык с нуля, очень маловероятно, что ты вырулишь туда, куда и хотел изначально. Посмотри, с чего начал Раст и куда вырулил. Список желаемых тобой фич может оказаться противоречивым и нереализуемым одновременно, что может быть не очевидно со стороны. И получиться, как сейчас часто говорят, «за что боролся»?
Привет, Антон! Слово «просто» действительно ключевое. Был период когда я подумывал об этом — причем не замахиваясь на полноценный язык, хотя бы для текущих нужд. Хотел развить идею LLJS компиляцией в asm.js и в JVM байткод. Но понял что ресурсов, которые нужно будет потратить на это дело и знаний которые нужно приобрести, слишком много.
Выбор автора расходится с общими представлениями о разработке продукта.

Минимум вопросов:
— идеальный язык для каких задач?
— должен ли быть пакетный менеджер?
— какова активность комьюнити?
— имеется ли среда разработки и отладки?
— на сколько быстро можно будет найти замену разработчику?
Очевидно же, что автор открыл для себя лучший язык — русский матерный. Небольшой словарь, краткость, огромная экспрессивная мощь и т.п. ;)
… с успехом может быть использован для формулировки любой задачи, и даже её выполнения (если под рукой есть парочка подчинённых)…
при наличии js-разработчиков, опять же, может получиться неплохой javascript
Я хочу кросс-платформенность с обязательной компиляцией в JavaScript.

Наилучшая кросс-платформенность + компиляция в любой язык
platoff ждал третьей части, но что-то ее пока нет, так что, зная спойлер, спрошу здесь. А почему не D?
Автор видимо перегорел от счастья и бросил язык.
Соответственно и статью можно не ждать.

Кому интересно, что за язык
Nim. Он написал в своем твиттере.


Хз, я рассматривал этот язык, даже писать пробовал. Мой вывод:
  • Документация непонятная, туториала нет, примеров почти нет
  • Неизвестно кто разрабатывает
  • Если использовать для веб-разработки, то фреймворков нет. Есть два, весьма скромных
  • Если на в скидку сравнивать с Go для веба, то на Go надежды больше (как бы Google разрабатывает), да и проще он.
  • Готовых решений/библиотек очень мало


Выход есть: всем хабром, взяться за язык, написать полезные штуки и упорно пропихивать в продакшен — но зачем? :)
Все коменты не читал, но первая строчка сразу напомнила «Я джва года ждал».
Стесняюсь спросить: с core.typed что не так?
да, не панацея, но уменьшение требований к объёму памяти разработчика же… А я так понял, что это единственный мало-мальски веский аргумент автора против clojure (ну и всей динамической типизации). (ну ещё есть шутка про «ололо, лисп, борода, дветысячипятнадцатый!», которая ещё более бородата, чем воображаемый автором лисп-программист)
Похоже фальшстарт, и поиски продолжаются.
Сравнить Clojure с пхп — это сильно.

Статически типизированный язык предоставляет свою систему типов, в которой некоторые вещи могут выражаться с большим трудом. Динамически типизированные языки дают возможность эксперементировать с таким вещами, которые в распространенные системы типов не укладываются, но не на столько важными, что бы под них писать всой язык. Я с такими сталкивался дважды (решенчатое раследование и наследование грамматик)

В Scala type class — это параметризованный имплисит. Все банально, не надо было ни чего искать.
Что до сложности, то надо различать сложность разработки хорошей библиотеки и сложность использования хорошей библиотеки. Хорошие библиотеки сложно разрабатывать на любом языке. На некоторых даже не возможно. HList — для библиотек.
Sign up to leave a comment.

Articles