LINUX.ORG.RU

Помогите господа маститые программеры


0

0

Понимаю, что такие темы вызывают флуд, флейм и холивар. Но все таки прошу сегодня помощи у больших программистов. Вот в чем дело - решил посвятить себя всегод функциональным языкам и соотвественно программироавнию на них. На глаза попались такие языки как Erlang и Haskell. Первый отмел по личным предпочтениям. Так же прочитал о LISP, в частности Scheme и Common LISP. Прошу вот ответить на что - что посоветуете изучать и какие книги при этом лучше брать (предпочтительно конечно русские, так как приятней, но инглиш понимю хорошо). Ну и конечно IDE для всего этого. Заранее благадарю.

>решил посвятить себя всегод функциональным языкам и соотвественно программироавнию на них

Common Lisp не является функциональным языком. Scheme променяла многие фишки CL на ФП, не является чисто функциональным языком. Erlang - это такая библиотека под С для построения распределенных event-driven систем ;)). Haskell - чисто ФП язык, что с одной стороны дает много преимуществ, с другой стороны - готовься в уме считать комбинации нескольких монад (в реальных задачах). Ocaml похож на хаскель, но не является чисто функциональным языком.

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

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

После чего нужно понять, что функциональная композиция (.) и монадический bind (>>=) одно и то же, а все сложности, связанные с монадами - "расплата" за "контейнерный" тип. И как функция от многих аргументов сводится к "комбинаторам" тиа a 'op' b 'op' c ... == op a b c ...

Ну а после чего придет понимание, что ФП ради ФП не бывает.

Мой тебе совет, обрати внимание на разработку DSL (проблемно-ориентированнх языков), все что ты ищешь - там. Я тебе гарантирую.

Macil ★★★★★
()
Ответ на: комментарий от Macil

Спасибо за советы. Может тогда еще объясните в чем приемущества Haskell перед Lisp или наоброт. Особенно было бы интересно спрактической точки зрения узнать.

lemoor88
() автор топика
Ответ на: комментарий от lemoor88

>Спасибо за советы. Может тогда еще объясните в чем приемущества Haskell перед Lisp или наоброт. Особенно было бы интересно спрактической точки зрения узнать.

ответ читай тут:

http://www.amazon.co.uk/Haskell-Road-Logic-Maths-Programming/dp/0954300696/re...

jtootf ★★★★★
()
Ответ на: комментарий от lemoor88

>приемущества Haskell перед Lisp или наоброт.

Нет никаких преимуществ хаскеля перед лиспом. Их между собой сравнивать некорректно.

Хаскель - это максимальное приближение к математической нотации и обкатка инновационных вещей типа типизации Хиндли-Милнера и GADT.

Коммон Лисп - это метапрограммирование. Т.е. мы делаем программу, которая делает программу, которая ... На лиспе ты программируешь в терминах AST (абстрактного синтаксического дерева т.е. того, что получается когда выражение на языке проходят через парсер), грубо говря, любая лисп-форма принимает дерево символов и дерево символов же возвращает (по-другому дерево символов называется S-выражение или S-expression).

Это не значит что у лиспа нет синтаксиса. Он у него есть, притом программист может им очень гибко управлять через SET-MACRO-CHARACTER и SET-DISPATCH-MACRO-CHARACTER т.е. конструкции типа ' (quote) или #' (functional quote) не являются аттрибутами языка, как например операторные скобки в C, а просто стандартная настройка лисп-системы.

Что же скрывается за символом - дело третье. Т.е. выражение (foo bar baz) может значить вообще все что угодно и не обязательно каждый раз одинаково. Все определяется тем, как конкретный символ связан со своим "значением", это может быть переменная, функция, какой-то другой объект, плюс многое зависит от того в каком окружении это связывание произошло. Ну и мы можем скормить выражение самому лиспу c помощью EVAL, а можем сами разбирать, как в режиме интерпретации, так и в режиме компиляции, вообще хоть в машинный код.

В лиспе нет разницы между eDSL и DSL. Захотели - приделали "морду" к нашему eDSL'ю. Самый простой пример - скомпилировать регулярное выражение.

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

В принципе, CL, как язык общего назначения достаточно силен, один механизм condition'ов чего только стоит, не говоря уж про тот факт, что CL - "полностью объектно-ориентированный язык". Но использовать его таким образом все-равно что забивать гвозди микроскопом...

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

Macil ★★★★★
()
Ответ на: комментарий от Macil

>Дело в том, что для того, чтобы эффективно использовать лисп и хаскель, должны возникнуть задачи, для решений которых эти языки лучше всего подходят. Для хаскеля - это что-то вычислительное-параллельное. Для лиспа - это разработка DSL.

писать DSL (и eDSL) на Haskell ненамного сложнее чем на CL. благо и Parsec есть, и квазиквотация с GHC > 6.9

это уж скорее вопрос стиля - кому-то ближе комбинаторы, кому-то всепоглощающее AST (так и хочется сказать "AST головного мозга")

ну и немножко сахарку (критика SICP):

http://kmmbvnr.livejournal.com/62197.html

jtootf ★★★★★
()
Ответ на: комментарий от tailgunner

>Отлично :) А есть учебник вроде SICP, но на чем-нибудь статически типизированном (Хаскель, *ML)?

есть The Craft Of Functional Programming, два варианта: Miranda и Haskell, но там скорее основы - т.е. первые две-три главы SICP'а

есть чудесная читаемая мною сейчас Haskell Road To Logic, Maths, And Programming (там выше давал ссылку на amazon) - там, судя по всему, уровень повыше SICP'овского

а такого чтобы один к одному - не встречал

jtootf ★★★★★
()
Ответ на: комментарий от tailgunner

Кузино и Мони примерно того же уровня, что и SICP, там Caml Light.

Лекции Харрисона - тоже caml light, уровень поглубже чем SICP, но охват тем сильно уже.

anonymous
()
Ответ на: комментарий от jtootf

> это уж скорее вопрос стиля - кому-то ближе комбинаторы, кому-то всепоглощающее AST (так и хочется сказать "AST головного мозга")

Аллё! Ты какого сраёна?!? Это вопрос вовсе не только стиля, но и производительности. Правда, есть конечно же и Template Haskell, но это ровно то же самое "AST головного мозга".

anonymous
()
Ответ на: комментарий от jtootf

>это уж скорее вопрос стиля - кому-то ближе комбинаторы, кому-то всепоглощающее AST

Комбинаторы хороши тем, что такую программу можно распараллеливать и результаты кешировать. Настоящие проблемы начинаются тогда, когда в стройную функциональную программу вторгается real^W world.

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

Как-то я попробовал в хаскеле написать обработчик ошибок и пришел к тому, что это нужно либо делать через монаду Error (она же Either), либо по эрланговскому принципу: при возникновении ошибки процесс обязан как можно быстрее сдохнуть. В принципе, можно еще через STM, но на осознание этой концепции меня не хватило.

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

Macil ★★★★★
()
Ответ на: комментарий от anonymous

> Кузино и Мони примерно того же уровня, что и SICP

"The Functional Approach to Programming with Caml"?

> там Caml Light.

Caml снизу вверх совместим с Ocaml, так?

tailgunner ★★★★★
()
Ответ на: комментарий от imp

>Даже проще + есть еще и BNF Converter

Еще один DSL, а потом еще один DSL, чтобы разработать свой собственный DSL. Плавали, знаем :(

Macil ★★★★★
()
Ответ на: комментарий от Macil

>Еще один DSL, а потом еще один DSL, чтобы разработать свой собственный DSL. Плавали, знаем :(

сначала хотел сказать, что всё намного проще

а потом вспомнил о том, что то, что ты написал - это и есть Ъ LISP-way. в чём же проблема-то с иерархией DSL'ей? :)

jtootf ★★★★★
()
Ответ на: комментарий от tailgunner

> "The Functional Approach to Programming with Caml"?

Оно самое.

> Caml снизу вверх совместим с Ocaml, так?

Не совсем, синтаксис несколько отличается. Например, инфиксные функции по другому определяются, есть отличия в синтаксисе конструкторов ADT.

anonymous
()
Ответ на: комментарий от anonymous

>Это вопрос вовсе не только стиля, но и производительности

производительности ЧЕГО? производительности ГДЕ? анонимус, ты какой-то очень невнятный сегодня

jtootf ★★★★★
()
Ответ на: комментарий от jtootf

>проблема-то с иерархией DSL'ей? :)

Проблема в том, что это во-первых не "твой" DSL. Т.е. своя кривая обучения, свой кривой синтаксис и т.д. Во-вторых проблемы с расширяемостью. Понятно конечно, что это опен-сорс и все такое, но согласись, что eDSL расширяется намного проще и лучше, чем DSL. Причем в лиспе есть такая мега вещь как shadowing, как на уровне пакетов, так и на уровне лексического окружения... Баловство это все, конечно, но позволяет быть проще и гибче. И в третьих у eDSL _всегда_ одинаковый синтаксис (не нужно помнить, что DSL1 присваивание осуществляется с помощью := а в DSL2 с помощью = и т.п.)

Macil ★★★★★
()
Ответ на: комментарий от jtootf

> производительности ЧЕГО? производительности ГДЕ?

Производительность кода, написанного на этом твоём DSL.

На комбинаторах ты максимум тормозной интерпретатор сделаешь. На метапрограммировании над AST можешь хоть сразу машинный код из DSL генерить.

anonymous
()
Ответ на: комментарий от anonymous

>Производительность кода, написанного на этом твоём DSL

бред. какая разница, какими методами я буду писать кодогенератор?

>На комбинаторах ты максимум тормозной интерпретатор сделаешь. На метапрограммировании над AST можешь хоть сразу машинный код из DSL генерить

ты не в теме. или, что тоже возможно, тролль

jtootf ★★★★★
()
Ответ на: комментарий от jtootf

> бред. какая разница, какими методами я буду писать кодогенератор?

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

> ты не в теме

Возможно. Но тогда изволь показать пример, опровергающий мои утверждения.

anonymous
()
Ответ на: комментарий от Macil

>Common Lisp не является функциональным языком
В каком месте?

anonymous
()
Ответ на: комментарий от jtootf

>http://kmmbvnr.livejournal.com/62197.html
Херня какая, а.

Типа, в sicp нет паттерн матчинга, а заодно и ленивых вычислений(которые там есть по сути), поэтому sicp - говно, и схема заодно с ней, и сам лисп заодно со схемой.
Очередной тупоголовый фанатик хаскеля.

anonymous
()
Ответ на: комментарий от anonymous

Назвать Вадлера "тупоголовым фанатиком" - это надо быть уж совсем неграмотным и дремучим. Гуляй мимо.

anonymous
()
Ответ на: комментарий от anonymous

>Разница такая, что с метапрограммированием никакого кодогенератора писать не надо вообще, оно само получится, бесплатно

так. давай определимся - у нас DSL или eDSL? если первое, то кодогенератор нам нужен в любом случае - нам надо сгенерировать результирующий язык на выходе. и не важно, на чём ты будешь этот кодогенератор писать - важно только то, как

если же у нас eDSL, то какие у тебя претензии, например, к Parsec? к Reactive? они полностью на комбинаторах, никакого метапрограммирования. а если оно таки нужно, то вот тебе примеры:

http://www.eecs.harvard.edu/~mainland/ghc-quasiquoting/

там ссылка на статью, в которой в качестве eDSL в Haskell зашивается ассемблер и TinyC

ещё к вопросу о eDSL в Haskell:

http://zelych.livejournal.com/9922.html?thread=18370#t18370

это про Harpy, если что. кстати, есть аналоги для CL?

jtootf ★★★★★
()
Ответ на: комментарий от jtootf

> так. давай определимся - у нас DSL или eDSL?

Не важно, на самом деле.

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

Ну, если заморачиваться над эфемерной разницей между подходами Happy и Parsec - то как-то так. Но кого это волнует?

> если же у нас eDSL, то какие у тебя претензии, например, к Parsec?

Тормоз он. Сравни со встраиваемыми в Common Lisp компилирующими реализациями, нупример, того же Packrat.

> они полностью на комбинаторах, никакого метапрограммирования.

И потому тормоза. Для некоторых простых задач этого достаточно, но в общем случае ни фига не работает. Следай на комбинаторах тот же аналог LINQ, с полноценной раскруткой вложенных map-ов (про rewrite rules знаю - это очень частное решение, не годится в этой задаче).

> а если оно таки нужно, то вот тебе примеры: Я про TH выше уже писал - это ровно тот же подход, что и в Lisp, то есть, по твоей классификации - AST головного мозга. И к TH у меня множество претензий - полноценного лиспа он не заменяет, хотя бы по той причине, что синтаксис макроподстановки отличается от синтаксиса всех прочих конструкций, и по причине невозможности изменить синтаксис внутри самой макры - она работает с тем же AST, что и Haskell.

> это про Harpy, если что. кстати, есть аналоги для CL?

Полно, во многих реализациях Лиспа есть встраиваемый ассемблер.

anonymous
()
Ответ на: комментарий от anonymous

>Тормоз он. Сравни со встраиваемыми в Common Lisp компилирующими реализациями, нупример, того же Packrat.

Да он медленный, но если его гонять на стадии компиляции через Template Haskell то кого это волнует?

А так можешь сравнить по скорости с BNF converter / Happy - они заметно быстрее.

>И потому тормоза. Для некоторых простых задач этого достаточно, но в общем случае ни фига не работает. Следай на комбинаторах тот же аналог LINQ, с полноценной раскруткой вложенных map-ов (про rewrite rules знаю - это очень частное решение, не годится в этой задаче).

Чем это rewrite rules не угодили интересно?

imp ★★
()
Ответ на: комментарий от imp

> Да он медленный, но если его гонять на стадии компиляции через Template Haskell то кого это волнует?

Мы и сравниваем метапрограммирование, то есть, генерацию кода во время компиляции, AST головного мозга, с "кошерными" комбинаторами.

> Чем это rewrite rules не угодили интересно?

Тем, что далеко не на все случаи шаблон нарисовать можно, тогда как foreach/yield в C# компилируется корректно всегда.

anonymous
()
Ответ на: комментарий от anonymous

>Ну, если заморачиваться над эфемерной разницей между подходами Happy и Parsec - то как-то так. Но кого это волнует?

хм? подход Parsec по ряду причин намного удобней. по ним же - существенно тормозней. ты об этом?

>Тормоз он. Сравни со встраиваемыми в Common Lisp компилирующими реализациями, нупример, того же Packrat

сравню

>Для некоторых простых задач этого достаточно, но в общем случае ни фига не работает

в общем случае вообще как правило VB.Net используют

>Я про TH выше уже писал

это не TH. вернее, не только TH

jtootf ★★★★★
()
Ответ на: комментарий от jtootf

> хм? подход Parsec по ряду причин намного удобней. по ним же - существенно тормозней. ты об этом?

Ну, если с Happy (и прочими [E/L]BNF) сравнивать - то удобнее. Если с PEG - то уже ни фига подобного. Так что никакой связи между удобством и тормозами нет. На метапрограммировании можно делать и удобно и быстро одновременно.

anonymous
()
Ответ на: комментарий от anonymous

>Мы и сравниваем метапрограммирование, то есть, генерацию кода во время компиляции, AST головного мозга, с "кошерными" комбинаторами.

Одно другому не мешает. Комбинаторы полезны и сами по себе. Для большинства задач разница в скорости совершенно не принципиальна.

>Тем, что далеко не на все случаи шаблон нарисовать можно, тогда как foreach/yield в C# компилируется корректно всегда.

list fusion тоже всегда работает как ни странно.

imp ★★
()
Ответ на: комментарий от jtootf

> http://kmmbvnr.livejournal.com/62197.html

Сие по-моему есть отчаянное ковыряние в комариных жопках. Мне как стороннему наблюдателю принципиального качественного положительного отличия между схемой и хаскелем (мирандой) для задачи обучения студентишек не видно.

anonymous
()
Ответ на: комментарий от anonymous

>Тормоз он. Сравни...

Кстати, я не стал бы обсуждать на _таком_ уровне. "Тормознутось" - понятие очень относительное.

Кроме того, как мне кажется, мы движемся назад в будущее: помнится в середине 90-х были распространены серваки с десятков pentium'ов, плюс еще десяток 486-х для как процессоры ввода-вывода.

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

Macil ★★★★★
()
Ответ на: комментарий от anonymous

>принципиального качественного положительного отличия

щито?

jtootf ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.