суббота, 4 сентября 2010 г.

Язык для быстрого прототипирования

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

Другое дело Лисп! Написание нетривиального кода начинается опять с блокнота и ручки, но, накарябав пару каракулей, думаешь: "Какого чёрта!", и пишешь примерно в тех же терминах каракулей прямо лисповым кодом. Небольшие, логически независимые куски кода проверяются прямо в редакторе (слава REPL'у!), структуры данных меняются и дополняются сто раз в час, прямо по ходу развития мысли и выяснения деталей. Компилятор свободу практически не ограничивает, он спокойно съедает код с явными ошибками, и позволяет вернуться к их исправлению позже, когда более важная работа выполнена. Программа рождается на кончиках пальцев, кои, как известно, являются механическими окончаниями мозга :)

Лисп - язык для практических хакеров, не математиков-теоретиков.

9 комментариев:

  1. Вот ровно также пишется код на Хаскеле. Только тут ещё добавляется пункт "если ты пишешь уж слишком явную фигню, то тебе об этом скажут".

    ОтветитьУдалить
  2. Да, кстати. Впервые я почувствовал вышеописанное при работе на OCaml. Да, он как и Haskell, больше ограничивает, чем CL, но порой типизация действительно полезна. Я вот так и не решил, при написании кода на каком из этих языков получаю большее эстетическое удовольствие.

    ОтветитьУдалить
  3. И да, забыл добавить, что именно на Haskell такого ощущения лично у меня почему-то нет.

    ОтветитьУдалить
  4. Ровно также пишется код на любом языке, который:

    1. хорошо знаком
    2. имеет приличный REPL.

    ОтветитьУдалить
  5. > migmit
    Категорически нет.

    >dream.designer
    Не работал с OCaml. Чисто ради праздного любопытства: а что он действительно позволяет посылать выражения на выполнение в репл не выходя из исходника? И действительно есть ощутимый профит от этого для языка не основанного на s-выражениях? Что-то сомневаюсь ...

    >daapp
    Это заблуждение.

    А насчёт заметки.
    Ну что сказать, поработав уже приличное время в таком стиле, я нахожу нелепым - работать по другому. Это тоже самое что, вместо того тобы чтобы зажечь газовую плиту зажигалкой - берёшь палочку и дощечку и начинаешь добывать огонь, как в старые "добрые" пещерные времена :))

    ОтветитьУдалить
  6. >linkfly
    Да, возможна разработка почти как в Lisp. Пишем кусок кода, посылаем в REPL, проверяем. Не понимаю, какой принципиальный профит тут должен быть от s-выражений.

    В Lisp больше свободы, это да. Из-за динамического связывания можно скомпилировать функцию, вызывающую еще не определенные функции. Поэтому можно, кстати, разрабатывать и "сверху вниз", и вообще как заблагорассудится. В OCaml так нельзя, ибо связывание статическое. Зато имеем бонус в виде статической проверки типов, которая, не смотря на заявления апологетов динамической типизации, ловит ощутимое количество ошибок. И чем сложнее программа, типы, логика, тем эта помощь ощутимее, хотя разумеется, она не "абсолютна" и вполне можно писать качественные программы и без нее.

    ОтветитьУдалить
  7. Но справедливости ради стоит сказать, что такая инкрементальная разработка среди пользователей OCaml распространена менее, чем среди пользователей Lisp. То есть немалое количество программистов ведут разработку так, как на C: пишут программы, компилируют, проверяют целиком, чего я решительно не понимаю. Для меня инкрементальная разработка, с которой я столкнулся вплотную впервые лет 5 назад именно при использовании OCaml, стала откровением и отказываться от нее теперь никак не хочется.

    В случае Haskell тоже есть некоторое подобие REPL, можно посылать на компиляцию модуль целиком, а потом в REPL запускать отдельные функции. Но лично у меня ощущения уже не те, происходит все же некоторое переключение контекста. И среди разработчиков на Haskell этим походу пользуется еще меньшее количество людей.

    ОтветитьУдалить
  8. > Да, возможна разработка почти как в Lisp. Пишем кусок кода, посылаем в REPL, проверяем. Не понимаю, какой принципиальный профит тут должен быть от s-выражений.

    В Емаксе по нажатию кейбиндига в REPL посылается sexp, за скобкой которого стоит курсор. Интересно, как это происходит в REPL-capable языках с традиционным синтаксисом? Выделять регион, посылать его?

    И без понятия "образ программы", в котором код эволюционирует по ходу разработки, от REPL'а тоже смысла не очень-то много.

    Полезность статической проверки типов несколько преувеличена. Да, бывает полезной. Нет, без неё тоже нормально.

    ОтветитьУдалить
  9. >В Емаксе по нажатию кейбиндига в REPL посылается sexp, за скобкой которого стоит курсор. Интересно, как это происходит в REPL-capable языках с традиционным синтаксисом? Выделять регион, посылать его?

    С регионом не очень удобно, хотя можно и так. То, что используется чаще всего, -- tuareg-eval-phrase (вызывается по C-x C-e): синтаксический анализатор смотрит код впереди курсора и выделяет одну до него стоящую сущность (определение функции, класса, просто инструкцию), ее и компилирует и выполняет. Мне сложно сейчас формализовать причины, никогда всерьез не задумывался об этом, но по субъективным впечатлениям, ощущаемым очень четко (это по сравнению например с Python, у которого есть более-менее нормальная интеграция в Emacs с REPL, но в котором из-за синтаксиса приходится пользоваться именно выделением региона) синтаксис OCaml не является большим препятствием для использования с REPL.

    > И без понятия "образ программы", в котором код эволюционирует по ходу разработки, от REPL'а тоже смысла не очень-то много.

    Поверьте, его не мало. Я соглашусь, что в Lisp меньше ограничений для этой модели разработки, но в случае OCaml все вполне удобно и полезно. "Образ программы" позволяет работать на уровне программы целиком, и это очень удобно. В случае OCaml без ухищрений работа в REPL как правило ограничивается написанием одной единицы компиляции, то есть сеанс REPL как-правило куда короче. Остальные же различия (недостатки и достоинства) вытекают из динамической против статической природы этих языков. В любом случае интерактивная разработка в случае OCaml возможна и дает множество плюсов, знакомых вам по разработке на CL. То есть возможность тут же запускать разрабатываемый вами код для проверки, уточнять и детализировать его. Программа по-прежнему "живая", а выводимые типы к тому же дают дополнительную обратную связь, бывает совсем нелишнюю.

    > Полезность статической проверки типов несколько преувеличена. Да, бывает полезной. Нет, без неё тоже нормально.

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

    ОтветитьУдалить

Архив блога