Пользователь
0,0
рейтинг
18 июля 2011 в 11:01

Разработка → Haskell в настоящем проекте

Мне приходилось участвовать в проектах на c++ с количеством строк более 600 000. Поэтому сложно назвать проект на 5000 строк настоящим. И тем не менее, для хаскеля и мотивации just for fun это немалый объём.

Эта небольшая программа[1] пишется в свободное время, поэтому времени ей сильно не хватает.

Хотелось бы описать некоторые впечатления об использовании хаскеля на практике.


Реакция пользователей


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

Установка ни у кого не вызвала серьёзных проблем. Были лишь небольшие проблемы, например, с тем что отключены cookies. Или на 64-битной системе был запущен двоичный файл для 32-битных систем.

Проблемы haskell


Проблемы языка

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

За время работы над проектом встретилась только одна проблема, связанная именно с языком. В определённый момент потребовалось добавить в большой стек трансформеров монад ещё одну монаду[2]. Что оказалось нетривиальной задачей. С помощью чтения документации и дружелюбной помощи хаскелистов в irc проблема решилась за вечер. Честно признаться это место можно было сделать проще, но именно такая реализация позволила защититься статической типизацией от целого класса ошибок. Если будут интересны подробности, напишу отдельный пост.

Порог вхождения и кривая обучения

Существует также мнение что порог вхождения в хаскель очень велик. А кривая обучения слишком растянута. По этому поводу могу сказать следующее.

Когда я только начинал изучать хаскель, я решал одну небольшую проблему. В хаскеле нет многострочных строк в исходниках. То есть нельзя в исходник добавить большой текст и получить валидную строковую константу.
-- Так нельзя, ошибка синтаксиса
text1 = "Многострочный
 текст" 
 
-- А так можно
text2 = unlines ["Многострочный",
 "текст"]
 
-- и так можно
text3 = "Многострочный\n\
 \текст"


Я написал программу на 600 строк, которая принимала на вход специальный текстовый файл и генерировала по нему исходник на хаскеле с многострочными строковыми константами. Это позволило при разработке web-приложений встраивать все тексты прямо в бинарник.

Чем дальше я изучал хаскель, тем больше понимал, что этот код очень плох. Там не было монад состояния, для парсинга не использовалась библиотека parsec. Всё было сделано простым кодом с явным указанием всех параметров и использованием только тривиальных конструкций.

Но этот код я с лёгкостью понимал даже через 2 года. И он меня полностью устраивал. Но приближался релиз проекта, для сборки которго нужна эта утилита. Стало стыдно выпускать её в таком виде. Поэтому я сел и за полчаса переписал её на parsec[3].

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

Проблемы взаимодействия с другими системами

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

Для веб-приложений это обычная работа по вёрстке веб-страниц и разработке javascript-кода. Сюда же прилагаются проблемы кроссбраузерной совместимости и прочие прелести веб-разрабоотки.

На системной стороне также требуется отдельная работа. Скрипты установки, инициализация, взаимодействие с системными динамическими библиотеками. Всё это требует тех же навыков, что и любая системная разработка под linux.

Библиотеки. Помимо родных библиотек, для хаскеля создано большое число обёрток вокруг сишных библиотек. Но далеко не все. В ходе работы пришлось писать собственную обёртку вокруг библиотеки PAM[4], так как готовых реализаций действительно не было. Как оказалось, писать интерфейс к сишному коду на хаскеле достаточно просто.

Сторонники питона при сравнении с хаскелем утверждают, что для питона написаны уже почти все библиотеки. Но мне приходилось участвовать в одном питоновском проекте, в котором был с нуля переписан существующий пакет для доступа к сишной библиотеке. Потому что существующий код был ужасен. Стало быть это преимущество питона не так уж велико.

Отдельно стоит отметить проблему создания пакетов для дистрибутивов linux. Это не так просто, вся инфраструктура пакетирования заточена под традиционные компиляторы и языки. Тема создания пакетов для программ на хаскеле заслуживает отдельного поста. Порадовало, что программы на хаскеле собираются даже для таких проверенных временем систем, как Red Hat Enterprise Linux 5. Чтобы запустить там приложение на питоне, вам потребуется добиться работы на python 2.4. Либо попытаться запустить там более новый интерпретатор и получить ещё больше проблем с установкой и поддержкой.

От каких проблем haskell избавляет


Не буду полностью пересказывать параграф «Почему хаскель?» из введения с официального сайта языка[5].

Приведу краткий список преимуществ языка из этого параграфа:
  • Значительно увеличенная производительность программиста.
  • Более лаконичный, понятный код, более дешёвый в сопровождении.
  • Меньше ошибок, более надёжные программы.
  • Меньше «семантическая пропасть» между программистом и языком.
  • Более быстрый выпуск продукта.

Как показала практика, они не врут.

Но от себя я бы добавил ещё один пункт в этот список. Программирование на хаскеле приносит удовольствие. Те же самые эмоции, наверное, были у программистов середины 20 века, когда впервые появился ассемблер. Такое же упрощение работы было при переходе с ассемблера на фортран.

На хаскеле больше нет необходимости управлять поименованными областями памяти(переменными). Разработчику достаются только поименованные неизменяемые значения. О представлении которых в памяти компилятор заботится сам. Это является существенной автоматизацией труда программиста.

Что ж, подождём пока бизнес обратит на хаскель более пристальное внимание. Рискнув использовать хаскель в продакшене, можно всё потерять получить значительное конкурентное преимущество.

[1] http://iptadmin.confmgr.org
[2] Ссылка на исходник, нужный код в функции authorize
[3] http://patch-tag.com/r/etarasov/iptadmin/snapshot/current/content/pretty/util/ptmpl/src/Main.hs
[4] http://hackage.haskell.org/package/pam-0.1
[5] http://haskell.org/haskellwiki/Introduction#Why_use_Haskell.3F
Евгений Тарасов @tranquil
карма
23,0
рейтинг 0,0
Пользователь
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (52)

  • +2
    Хорошая статья. Я вот присматривался одно время к Haskell, но потом по мере погружения в Common Lisp куда-то потерялась мотивация… Понял что меня в CL, по существу, всё устраивает, и пока нет нужды учить что-то новое. Наверное, то же можно сказать и про Haskell.
  • +1
    Спасибо, как раз сейчас учу хаскель и хочется разбираться с ним на основе проекта
  • +2
    Под кривой обучения обычно понимают не время на то чтобы написать свой велик, а время, через которое становится понятен чужой.

    Есть ли в проекте другие участники? Они все могут добавить в «большой стек трансформеров монад» и ещё одну? Кто-нибдуь может вточить хоть какую-нибудь фичу в проект пока Вы в отпуске?
  • 0
    Под кривой обучения обычно понимаю не время на то, чтобы написать свой велик, а время на то, чтобы понять чужой.

    В проекте есть другие люди? Они могут «добавить в большой стек трансформеров монад ещё одну монаду»? Кто-нибудь может добавить в проект хоть какую-нибудь фичу, пока Вы в отпуске?
    • 0
      Других участников проекта нет.

      Командное взаимодействие в проектах на хаскеле меня тоже очень интересует. Хотя не думаю, что особенности такого взаимодействия отличаются от других ЯП.

      В конференции джаббера периодически обсуждают код, обычно без проблем разбираются даже большие куски кода.
      • +1
        В конференциях, мягко говоря, специфическия публика. Интересен опыт передачи кода в поддержку не фанам языка, а более-менее случайной выборке коллег.

        Что меня давно смущает в хаскеле: не понятно какой разрыв порождает разница в знании языка между членами комманды. Я знаю что в С++, например, иногда разрыв оказывается непреодолим. И в то время как одни строят шаблоны 3-4 уровня другие скатываются в копипасту, просто не успевая догонять нарастающую абстрактность ядра проекта и изучать все задействуемые ньюансы языка.

        Я ни в коей мере не подвергаю сомнению отдачу от внедрения Haskell в вашем проекте. Но в «одно лицо» можно изучить и успешно внедрить всё, что угодно, при условии получения фана этим лицом.
        • 0
          Можете задать этот вопрос в списке рассылки haskell-cafe.

          В мире множество компаний, где над хаскельными проектами работают большие команды. Скорее всего они будут не против поделиться опытом.
        • 0
          У нас сейчас проект на хаскелле, который разрабатывают двое. Никакой специфики по сравнию с другими языками я не вижу. Код легче ревьювить, потому что его мало и есть типы.

          Код верхнего уровня понимают даже не разработчики, т.е. можно интуитивно догадаться, что он делает, т.к. фактически это DSL на предметной области
          • +1
            Что за проект, если не секрет, и каковы успехи?
            • +2
              Заказная разработка, демон для управления специфическим железом + месседжинг по сети. Ну как успехи? Планомерно делается, сделается — сдастся. В принципе, проект будет довольно заметный, закроем проект — расскажу. Никаких проблем от хаскелла нет.
              • +1
                А пишете с блэкджеком и трансформерами как и автор поста? Были ли проекты на хаскеле до этого у обоих? Как изучали всё это мясо Control.Monad?
                • +2
                  Конечно. А как без трансформеров, если нужно вложить несколько монад?

                  Control.Monad — это штука, сделанная для нашего с вами удобства, как ее не использовать?

                  Это мой второй и его первый коммерческий проект на haskell
                  • 0
                    Я понял — вы оба уже на 80м уровне =)
                    • 0
                      Да тут нет ничего сложного. Думайте о монаде, как о контексте.

                      Очевидно, что вам захочется в какой-то момент иметь вложенные контексты — например, программа должна уметь делать ввод-вывод и обладать состоянием.

                      А матан можно оставить для любителей — для того, что бы писать на haskell, он необязателен.
                • +1
                  Может быть вы не с того конца начали изучать?

                  После прочтения нескольких руководств и вхождения в тему большинство библиотек становятся поятными. И это мясо обычно не учат, а используют как справочник. А ещё чаще как справочник используют hoogle или hayoo и особо не запоминают какие функции и типы в каких модулях лежат.
                  • 0
                    А какая разница?

                    Живой пример. Открываем гитхаб, вбиваем слово «haskell» в поиск, кликаем в первый проект с понятной целью. Листаем исходники… И что видим? Видим какой-то ёбаный страх. На то чтобы вкурить сигнатуру любого из этих смайликов у меня уходит мин 10. Ещё мин 20 я пытаюсь соотнести её с окружающими выражениями и понять что оно делает всё вместе. Полтора часа на то, чтобы понять одну строчку кода. Их там 400, пускай собственно кода треть — 130. Получаем минимальное время на то, чтобы внести изменение в модуль ~ 4 недели. Ок, йа табуретко, считаем я в 4 раза тупее среднего разработчика. Один багфикс в неделю от свежего человека. На сколько? Пока каждый смайлик не попадётся раз 20 (для меня 100, но помним про табуретку), это три таких бага. Это даже не смешно, это 03 и принудительная госпитализация.
                    • +1
                      Конкретно этот пример требует понимания только типов данных, монад, библиотеки parsec и аппликативных функторов. Точнее даже не аппликативных функторов, а операторов <$> и <*> из Control.Applicative. Они делают простые вещи.
                      -- | Parses a BInt
                      getBInt :: Get BCode
                      getBInt = BInt . read <$> getWrapped 'i' 'e' intP
                          where intP = ((:) <$> char '-' <*> getDigits) <|> getDigits
                      

                      Ключевой момент здесь — тип Get a. Что это такое, я не знаю, в этом модуле не определён. Нужно найти откуда он импортируется и понять что он точно делает. По коду он похож на монаду парсинга, такую как в parsec.

                      getBInt :: Get BCode
                      

                      Сигнатура функции говорит, что в этом месте из какого-то потока токенов, может быть строки символов, парсится значение типа BCode.
                      Описание типа BCode есть в этом модуле.

                      BInt . read
                      

                      Это бесточечная нотация www.haskell.org/haskellwiki/Pointfree.
                      Вот сигнатура оператора (.):
                      (.) :: (b -> c) -> (a -> b) -> a -> c   -- Defined in GHC.Base
                      

                      Эта нотация как-то связана с комбинаторной логикой, но я не в куре математических тонкостей.
                      Оператор просто принимает на вход две функции и передаёт выход второй на вход первой. Получается новая функция, которая принимает на вход то, что принимает на вход вторая функция. Для удобства можно было бы записать так:
                      (BInt . read)
                      

                      Да, BInt — это один из конструкторов типа BCode. Это функция, которая принимает на вход Integer и возвращает BCode.

                      <$>
                      

                      Это то же самое, что fmap. Принимает на вход чистую функцию и функцию с побочным зффектом. Сначала вычисляет функцию с побочным эффектом, берёт оттуда чистый результат, подаёт на вход чистой функции. Результат всего этого делает побочным.
                      getWrapped 'i' 'e' intP
                      

                      Здесь происходит сам парсинг с побочным эффектом.

                      (:) -- оператор добавления элемента в начало списка
                      <$> <*> -- операторы из Control.Applicative, позволяют удобно комбинировать чистые функции и функции с эффектами.
                      <|> -- оператор выбора альтернатив парсера, такой же как в parsec.
                      

                      Т.е. intP — это парсер, для которого валидными строками являются символ "-", а потом то, что парсится функцией getDigits, либо просто то, что парсится функцией
                      getDigits без минуса. Возвращает он всегда точно такую же строку, которую распарсил. getDigits — это одна или больше цифр, что понятно из кода ниже.

                      getWrapped 'i' 'e' intP
                      

                      Это функция, которая делает из парсера intP новый парсер. Путём добавления в начало и в конец двух символов для парсинга.

                      -- | Get something wrapped in two Chars
                      getWrapped :: Char -> Char -> Get a -> Get a
                      getWrapped a b p = char a *> p <* char b
                      

                      Операторы (*>) и (<*) я никогда раньше не использовал и не знал что такое. Берём hoogle www.haskell.org/hoogle/, вводим там (*>). Попадаем в документацию к модулю Control.Applicative:
                      (*>) :: f a -> f b -> f b
                      Sequence actions, discarding the value of the first argument.
                      
                      (<*) :: f a -> f b -> f a
                      Sequence actions, discarding the value of the second argument. 
                      

                      Всё ясно, будем знать.

                      Итог: 20 секунд на понимание кода и 10 минут на этот текст. Какие недели, о чём вы?

                      Надеюсь, не стоит приводить примеры из c++, c#, python, perl, которые произведут точно такое же впечатление на первый взгляд?
                      • 0
                        Сурово… ПОпробую вечером осилить.
                      • +1
                        Немного ещё поразбирался, библиотеки парсеров здесь не используются. Есть только аппликативные функторы и Serialize — извлечение значений из байтовых потоков. Но смысл тот же.
                        • 0
                          Да не переживайте Вы так. Я правда верю, что можно писать на хаскеле просто и понятно (только не видно, чтобы кто-то так делал). Я даже верю в то, что в местах, вроде того что я привёл кто-то может разбираться.

                          Но порог из требуемых усилий (таланта?) для понимания такого кода даже для меня, в некоторой мере любителя разных ЯП, после полугода (достаточно ленивого надо признать) ковыряния самого Хаскеля и порта его библиотек на Скалу не преодолим.
                    • +1
                      Что-то я увлёкся кодом.

                      Но главная проблема я так понимаю не в коде, а в обучении. Свежего человека отправляем на неделю или сколько ему нужно знакомиться с базовыми концепциями. В дальнейшем при встрече каждого непонятного смайлика опытный человек говорит ему куда копать, что читать и что чёрт возьми тут происходит.

                      Как быстро вольётся — сложный вопрос. Но есть же разные участки кода по сложности. Самые простые вещи, думаю, можно начать писать очень быстро.
  • +1
    Хорошая статья, спасибо!

    Не подскажете, приходилось ли работать с кодировками отличными от UTF-8? Последний раз, когда я играл с Хаскеллом это было большой проблемой, расширение encoding не собиралось и ничего не работало.

    Было бы очень хорошо увидеть вторую часть статьи, где на цифрах показываются преимущества Хаскелла: на сколько выросла производительность труда, на сколько уменьшилось число ошибок, сравнение времени на разработку.
    • 0
      С другими кодировками работать не приходилось. Пакет encoding сейчас собирается без проблем.

      Как измерить в цифрах все эти показатели?

      Могу сказать только что на другом языке мне не хватило бы времени и терпения довести до логического завершения даже этот простой функционал.
      • 0
        > Как измерить в цифрах все эти показатели?

        Я представлял что-то в этом роде:

        • 0
          То есть для этой оценки нужно всё переписать на С++ или на другом сравниваемом языке, а потом сравнить?
          Даже если это сделать, то условия уже будут другие.
          • 0
            Нет, зачем переписывать. Можно сравнить с существующими примерами решения аналогичных задач на других языках.

            Просто без такого сравнения говорить о преимуществах немного преждевременно.
            • +2
              Ну не обязательно всё вносить с таблицу. Человек, много писавший на Си++, а затем попробовавший достаточно много писать на Хаскеле, чисто субъективно заметит разницу.
              Если интересуют измерения, то код со сплайновой геометрией на Haskell занял у меня 500 строк, на C++ 3к+. Ошибки и добавление функциональности сравнивать, к сожалению, конкретно в этом примере смысла нет, так как на Haskell был написан и отлажен прототип. И хотя доказательств для данного случая привести не могу, чисто субъективно REPL на порядок ускорил написание кода — можно было код исправлять почти на ходу и смотреть работоспособность.

              Я неоднократно слышал от различных людей, что если код на Haskell компилируется, то он работает (это, конечно, явное преувеличение, но имеется в виду эффект в сравнении с другим языком, обычно C++). Так что можно сделать примерный вывод о времени, потраченном на исправление багов.
              • 0
                О, спасибо! Это уже интереснее в плане статистики.

                Не подскажете, Вы один работали над кодом или в команде? Производительность в итоге была одинаковой?
                • 0
                  Писал один. Большим плюсом стоит отметить произвольный порядок определений, благодаря чему математические формулы (f =… x… y, где x = ..., y = ...) переписываются напрямую, в связи с чем есть основание полагать, что он достаточно понятен будет любому мало-мальски знакомому с Haskell программисту. Я вообще люблю писать именно в таком стиле, потому что после foo = пишется самое основное, а после where постепенно определяется всё остальное в порядке важности.

                  Производительность никогда не мерил (хотя, безусловно, было бы интересно попробовать), так как этот прототип был для уверенности, что я нигде не напортачил. Т.е. я написал, отладил, а потом большую часть времени переписывал это на C++, в основном занимаясь переводом всяких map и foldr.

                  Чтобы не лукавить, в целом настолько разительное отличие (аж 6 крат) в кол-ве строк встречается не так часто, это зависит как от задачи, так и от умения программиста пользоваться обобщённым кодом. Т.е. если сразу сесть после C++ на Haskell, то, например IO, скорее всего будет занимать столько же, так как по привычке будет переписано в лоб.
    • +1
      С кодировками сейчас проблем нет.
      encodeString CP1251 . decodeString UTF8
  • +1
    Спасибо за статью. При переходе на Хаскель я постепенно я всё больше убеждался, что некоторые якобы недостатки на самом деле лишь достоинства: отсутствие перегрузки; разделение именования типов, конструкторов и функций; неизменяемые значения.
    А эффект «компилируется значит работает» производит неизгладимое впечатление даже сейчас.
  • +2
    > Сторонники питона утверждают, что для него написаны уже почти все библиотеки. Но мне приходилось участвовать в одном питоновском проекте, в котором был с нуля переписан существующий пакет для доступа к сишной библиотеке. Потому что существующий код был ужасен. Стало быть это преимущество питона не так уж велико.

    Странная логика.
  • –1
    > Значительно увеличенная производительность программиста.
    > Более лаконичный, понятный код, более дешёвый в сопровождении.
    > Меньше ошибок, более надёжные программы.
    > Меньше «семантическая пропасть» между программистом и языком.
    > Более быстрый выпуск продукта.

    Сравнительные степени как-бэ требуют двух сравниваемых предметов. Всё это быстрее и лучше относительно чего? NASM? C? C++? Java? Python? Common Lisp? (на самом деле порядок случайный, а не то что вы подумали :P)
    • 0
      Относительно традиционных языков программирования.
      • +1
        Перечислите традиционные языки программирования, пожалуйста :)
        • –1
          Вы их перечислили ;)
      • +1
        Чем характеризуются “традиционные языки программирования”?

        (Серьёзно интересно посмотреть на набор характеристик под который подойдут все перечисленные мной языки, чтобы их можно было как одну сущность сравнивать, а не по отдельности)
        • 0
          Может термин «традиционные» не очень удачен.

          Это все обычные языки, в которых есть чёткий порядок выполнения инструкций и переменные.

          Некоторые ещё называют их императивными, противопоставляя их декларативным, таким как SQL, Haskell, язык Makefile и т.п.
  • 0
    Спасибо за статью.
    P.S. Скажите, вы всегда меряете объем проекта количеством строк?
    • 0
      А вы чем меряете?
  • 0
    К слову, попытался подтянуть encoding. Под Windows по-прежнему не собирается — как и ранее требуется файл system_encoding.h.

    stackoverflow.com/questions/4701585/how-to-install-haskell-module-encoding-0-6-3-on-windows — тут есть советы о том, как это можно поправить, но оба способа выглядят некрасиво.
  • 0
    > Порадовало, что программы на хаскеле собираются даже для таких проверенных временем систем, как Red Hat Enterprise Linux 5

    А собрать .deb сильно сложнее, чем .rpm? А то хотел взглянуть ваш проект на Убунте по-быстрому, а…
    • 0
      Наверное даже легче, в дебиане и убунту поддержка хаскеля получше чем в рэдхатовских дистрибутивах.

      Просто пока дело не дошло.

      Но можно воспользоваться пакетом tar.gz, там есть make install и даже make uninstall.
  • +1
    Не надо драматизировать. Хаскелл это круто (особенно в реальных проектах), но кидаться гавном в питон — уж извините.
    • 0
      Критика питона вообще не подразумевалась.

      Да, там больше библиотек. И не все библиотеки качественные. Но в хаскеле ещё меньше библиотек и также хватает шлака.

      По поводу работы на старых системах — очень часто системные администраторы жалуются что программисты приложений и сервисов хотят всё более новые и новые интерпретаторы. Это приводит к определённым проблемам.

      К слову, у меня одна хаскельная программа на centos5 в xen периодически зависала, в dmesg писались ошибки «4gb seg fixup». Перепробовал все советы, так и не вылечил. Пришлось ставить другую систему.
  • 0
    А в какой IDE писался проект, если не секрет? А то меня на пути изучения хаскеля останавливает только отсутсвие удобных (уровня VisualStudio или NetBeans) сред разработки…
    • 0
      Проект писался в vim.

      Для хаскеля существует IDE Leksah. Говорят, очень продвинутая штука.

      Также есть плагин для эклипса.

      Не знаю правда как они соотносятся с уровнем Visual Studio. Посмотреть подробнее не было времени.
  • 0
    К сожалению ни то, ни другое очень сильно не дотягивают по удобству использования до того, что я хочу, в Leksah у меня даже автодополнение не завелось…
    • 0
      При разработке на С++ я пользовался Visual Studio с плагином Visual Assist X.

      На мой взгляд писать на хаскеле в простом редакторе удобнее, чем писать на С++ с использованием этих средств.
      • 0
        Забыл уточнить, говоря про VisualStudio, я имел в виду VisualStudio для С#… Я, например, уже слишком привык к автодополнению, удобной навигации, инструментам для рефакторинга и отладчику, в редакторе буду работать на несколько порядков медленнее…
        • 0
          Да, приходилось однажды писать на С#. Впечатления — можно вообще ничего не запоминать, автодополнение пишет код само.

          И тем не менее, даже по сравнению с С# неудобств никаких не испытывал. Это сильно разные парадигмы. И если в одной жизненно необходимы инструменты автодополнения и навигации, не факт что это столь важно в другой.

          В редакторе на несколько порядков медленнее, а в leksah уже не на несколько порядков.
          • 0
            Писал, хоть и немного, в функциональном стиле на Common Lisp в Emacs + slime и на F# все в той же VS — удобно, leksah — нет, так что дело не в парадигме… В общем или leksah такой, или я его готовить не умею…

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