LINUX.ORG.RU

[функциональщина тред][вопрос к специалистам] что выбрать?


0

1

На работе занимаюсь обработкой текстов на естественном языке.

Собственно, пока задачи были маленькие и понятные (типа морфологии и т.п.), в качестве основного языка программирования использовался С++, который был выбран был по ряду причин: работает быстро, есть необходимые абстракции, ничего особого хитрого в задачах нет, заказчики нормально воспринимают код и могут его оценить.

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

А раз так, задумался я над тем какой язык выбрать для реализации. Собрав задницу в кулак и мозг в голову, я прошерстил интернет на предмет того каким решением можно воспользоваться в данной области, по результатам были отобраны следующие языки: Prolog, OCaml, Lisp, Scheme, Haskell и, как это ни странно, Python и Erlang.

Маленькое уточнение: требуется кроссплатформенное решение (windows, linux, macos) с возможностью компиляции в байт-код, хорошо бы иметь потоки, GUI не особо нужны, но будут плюсом, ide - неважно. Ещё один важный момент: наличие коммерческих реализаций с целью дальнейшего на них перехода или, как вариант, серьёзного бэкграунда.

Понятно, что на любом из этих языков можно реализовать всё что угодно, посему оценивались больше практические моменты использования, так вот, поковырявшись с вышеперечисленными языками я сделал для себя следующие выводы о готовности их к использованию в production:

  • Prolog - собственно существуют довольно вменяемые открытые и коммерческие реализации, однако общее состояние дел большее напоминает заброшенную ферму (например, разные реализации интерпретатора могут использовать разный синтаксис).
  • OCaml - неплохой претендент, немного стагнирует в своём развитии, но имеет существенную поддержку в лице INRIA (и небольшой буст со стороны в виде F#).
  • Lisp - весьма разносторонний язык, есть весьма вменяемая свободная реализация (Clozure CL; SBCL, увы, *nix oriented) и мега-буст с точки зрения коммерческих реализаций (Allegro CL, LispWorks), есть так же реализация под Java VM.
  • Scheme - сводный брат Lisp, ситуация обстоит приблизительно так же, хотя непонятно что с коммерческими реализациями и вообще Scheme имеет репутацию академического языка.
  • Haskell - довольно молодая и таки тёмная лошадка, есть некоторый зоопарк в реализациях, коммерческие средства отсутствуют, присутствует некоторый перекос ориентации в сторону *nix.
  • Python - довольно годный язык, но поддержка функциональной парадигмы там реализована довольно слабо + наличествуют всякие выкрутасы (типа GIL).
  • Erlang - годный Prolog-like язык, но меня смущает его ориентация на телеком.

Как то вот так у меня получилось (большого опыта работы с данными языками у меня нет, так что, если я где в оценке промахнулся, просьба тыкнуть меня носом :)).

Сам пока склоняюсь к Lisp.

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

Уф! Дописал. Всем откликнувшимся большое спасибо заранее. :)

ЗЫ brainf*ck и иже с ним не предлагать.

★★★★★

Ответ на: комментарий от linuxfan

Я не против прототипирования, я против неоправданной неэффективности.

Там, где надо быстро, из этого же DSL генерится VHDL. Только возня с полученным VHDL - это ещё дольше, чем с C/C++, хотя и несравнимо быстрее. Да и нет у меня на кухне FPGA-железки.

BTW сильно кастрированный аналог REPL'а для нативного кода называется gdb.

Вы программы в нативных кодах пишете и запускаете под gdb? И лисперов после этого называют извращенцами?

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

>в любом случае среднестатистическая сложность O(N*m) т.е. линейная

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

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

>Вы программы в нативных кодах пишете и запускаете под gdb? И лисперов после этого называют извращенцами?

Во-первых, gcc -O0 -fno-inline -g

Во-вторых, gdb позвоялет в том числе вызывать функции в контексте отлаживаемого процесса, не говоря уже о чтении/изменении значений переменных. Чем тебе не REPL?

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

Во-первых, gcc -O0 -fno-inline -g

Ну, если начать докапиваться до столбов, то таким лыком можно убрать проблемное место, которое в gdb как раз хотел отловить. Да и сам gdb для программы не совсем прозрачен.

Во-вторых, gdb позвоялет в том числе вызывать функции в контексте отлаживаемого процесса, не говоря уже о чтении/изменении значений переменных. Чем тебе не REPL?

Тем, что программа пишется на одном языке (Си, скажем), а отлаживается на другом (макросы gdb). Кроме того, REPL не ограничивается вызовом функций и чтением/изменением значений переменных.

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

>Тем, что программа пишется на одном языке (Си, скажем), а отлаживается на другом (макросы gdb). Кроме того, REPL не ограничивается вызовом функций и чтением/изменением значений переменных.

REPL = read-evaluate-print loop. Читать переменные мы можем, вычислять выражения тоже (включая вызов функции в контексте процесса). Вполне себе REPL с рядом ограничений.

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

Дожили, плюсист рассказывает лисперу про репл.

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

REPL = read-evaluate-print loop. Читать переменные мы можем, вычислять выражения тоже (включая вызов функции в контексте процесса). Вполне себе REPL с рядом ограничений.

Крестовые программисты тоже вполне себе программисты, только с рядом ограничений. Они и gdb назовут repl'ом для си.

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

число «возвратов» (или как там называется возврат к предыдущему подходящему случаю у жадных регэкспов) зависит от содержания входной строки

Да от регулярки оно зависит (по которой автомат строится) - вот построили автомат (по Кену Томпсону) и всё, m - константа, далее зависимость линейная и только от входной строки. Разные шаблоны ведь будут соответствовать разным автоматам - давая разный коэффициент при n.

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

>Крестовые программисты тоже вполне себе программисты, только с рядом ограничений. Они и gdb назовут repl'ом для си.

Ну извини, не виноватый я, что ты gdb не осилил.

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

>Я-то всё осилил, по чему дискутирую. А ты? :)

Осилил в нужной мне степени, поэтому вбрасываю тезис: для отладочной сборки, единственным отличием gdb от честного REPL'а является невозможность менять код программы на лету. В чем я заблуждаюсь?

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

>Гы, это ты так разработчику ядра говоришь???

Отладка ядра — детский лепет по сравнению с отладкой плюсового кода, обильно сдобренного шаблонами.

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

Отладка ядра — детский лепет по сравнению с отладкой плюсового кода, обильно сдобренного шаблонами.

Отладка в юзерспейсе по-умолчанию легче, чем в кернель-спейсе. Легче хотя бы уменьшением времени цикла «поправил, перекомпилировал, запустил, увидел результат». Второй важный аспект, усложняющий жизнь кернельщику, - невозможность интерактивной отладки. Конечно, есть kgdb и systemtap, но их далеко не везде и всегда воткнуть можно. Поэтому основной инструмент отладки кернельщина - голова и cscope. Третий аспект связан с непосредственной функцией ядра: управление ресурсами в многозадачной системе. Человеческий мозг плохо понимает параллельное исполнение с захватом общих ресурсов, которое ещё и может быть фейковым (т.е. несколько тасков на одном ядре), и плохо понимает, как нужно работать с этими ресурсами. Сколько лет проблемам переполнения буфера, неправильной работы со строками, рейс-кондишены, дэдлоки и т.п., а человеки всё на те же грабли наступают.

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

В чем я заблуждаюсь?

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

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

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

Командная строка bash считается?

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

> Отладка ядра — детский лепет по сравнению с отладкой плюсового кода, обильно сдобренного шаблонами.

в MSVC отладка плюсового кода очень проста и удобна, что-что, а дебагер у них отменный - и быстрый, и разворачивает классы/шаблоны и показывает в удобном виде

П.С. жаль, что его нет в линуксе, где я сейчас работаю :)

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

> В g++ сообщения об ошибках в шаблонном коде вообще ужоснах.

В MSVC такой же ужас, эту проблему вообще нельзя решить нормально без концептов.

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

> В g++ сообщения об ошибках в шаблонном коде вообще ужоснах.

скоро выйдет xCode 4 с полной интеграцией clang - в clang как раз сообщения вменяемые, + обещают его интеграцию с дебагером и редактором, если все будет как обещают( а Apple хоть и ругают, но дело они свое знают ) - то возможно перенесу работу под mac

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

> В MSVC такой же ужас, эту проблему вообще нельзя решить нормально без концептов.

я уже написал про clang выше, не буду повторяться

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

> Нда...

вас удивляет, что Apple сделала поддержку С++ у себя в компиляторе + IDE лучше чем в gcc + emacs? или что люди хотят пользоваться лучшим решением?

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

>Легче хотя бы уменьшением времени цикла «поправил, перекомпилировал, запустил, увидел результат».

Если ты разрабатываешь драйвер устройства, modprobe/rmmod тебе в помощь, но фатальные ошибки, требующие ребута, конечно, возможны. Если твоя разработка не связана с взаимодействием с железом — виртуальные машины тебе в помощь.

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

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

Третий аспект связан с непосредственной функцией ядра: управление ресурсами в многозадачной системе.

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

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

В юзерспейсе ходят ровно по тем же самым граблям.

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

> не знаю - не пробовал, вот кстати сравнение сообщений об ошибках:

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

http://clang.llvm.org/diagnostics.html


Ну, дык, детский сад. Вы пробовали заниматься метапрограммированием на C++? Со списками типов и т.п.? Когда при расскрытии 30-го вложенного шаблона система типов обнаруживает косяк? Что она при этом пишет? Можно ли в принципе это как либо разрулить?

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

>не знаю - не пробовал, вот кстати сравнение сообщений об ошибках

Тема шаблонов не раскрыта. Безобидный map<X,Y>::const_iterator i = map.begin выдает на gcc такой 3.14, что неподготовленный человек испытывает глубочайший культурный и нервный шок. Правда виноваты, в основном, длинные имена шаблонных типов.

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

>Когда при расскрытии 30-го вложенного шаблона система типов обнаруживает косяк? ... Можно ли в принципе это как либо разрулить?

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

Извините, не сдержался, так как сам однажды пал жертвой любителя «пометаниро^W пометапрограммировать».

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

Если ты разрабатываешь драйвер устройства, modprobe/rmmod тебе в помощь, но фатальные ошибки, требующие ребута, конечно, возможны. Если твоя разработка не связана с взаимодействием с железом — виртуальные машины тебе в помощь.

Какая разница? В случае крэша, oops'а или зависания всё равно ребут делать.

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

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

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

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

В ядре у тебя только Си и немножко ассемблера. Кроме сложности отладки кода есть ещё сложность в его написании.

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

> А почему тогда утверждаете?

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

Когда при расскрытии 30-го вложенного шаблона


а вы знаете толк в извращениях

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

>В случае крэша, oops'а или зависания всё равно ребут делать.

Виртуальную машину можно настроить так, что ребут займет порядка 10 секунд.

Кстати, могу рассказать случай из жизни, когда любитель метапрограммирования нахерачил таких шаблонов, что один файлик компилировался порядка 15-20 минут. Весь код был в хидерах и угадай, во что выливалось любое изменение кода? Угадай, как прекрасно его было отлаживать в gdb (hint: это было невозможно)?

Если упали на ранней стадии, то отладка очень затруднена.

С этим утверждением сложно спорить.

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

Если пишешь для себя, тогда да, не стоит. Если пишешь в команде, то тебя будут всегда заставлять писать поддерживаемый код. Никому не интересно, что на CL писать изящнее, а на Erlang можно наплодить десятки тысяч процессов. Зато руководителю (если он не полный дебил, конечно) всегда заботит вопрос: «А кто и как потом будет это поддерживать»?

В ядре у тебя только Си и немножко ассемблера.

Каким из этих двух слов ты хотел меня испугать?

Кроме сложности отладки кода есть ещё сложность в его написании.

Ты хочешь сказать, проект уровня firefox или postgresql писать очень легко? В юзерспейсе своих сложностей ой как хватает.

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

> Т.е. метапрограммирование на C++ - это таки извращение?

нет, уровень вложенности в 30 шаблонов - извращение, вы делаете странные выводы, извращение - это злоупотребление «фишками» языка, а не их наличие

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

> В таких случаях надо идти к автору сего чуда и пробивать сначала

в дыхалку


Вам сюда: http://www.boost.org/, заодно и в комитет по стандартизации С++ можете заглянуть - там кандидатов на «в дыхалку» тоже хватает.

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

> В этом треде есть люди, придерживающиеся другой точки зрения?

да :) у нас код для всяких Java, C#, Ruby etc. автоматически генерируется по результату парсинга С++-ых заголовочных файлов

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

> В этом треде есть люди, придерживающиеся другой точки зрения?

И не только в нём. Начните со Страуструпа и Степанова, Александреску оставите на десерт.

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

Виртуальную машину можно настроить так, что ребут займет порядка 10 секунд.

Так и делается, но это всего лишь срезание углов, а не решение проблемы.

Кстати, могу рассказать случай из жизни, когда любитель метапрограммирования нахерачил таких шаблонов, что один файлик компилировался порядка 15-20 минут. Весь код был в хидерах и угадай, во что выливалось любое изменение кода? Угадай, как прекрасно его было отлаживать в gdb (hint: это было невозможно)?

Чего гадать, я писал на плюсах с бустом ;) Компилируется долго, отлаживается тяжело. На лиспе такой же код компилируется быстро, отлаживается легко, выглядит более понятно. Profit!

К тому же, твой любитель нахерачил на шаблонах, а не на Си. Засунь эти же шаблоны по ту сторону CPL и ты автоматически получишь дополнительный геморрой в отладке.

Кстати, очень популярная крестовая библиотека для работы с СУБД в поточном стиле (OTL) весит килобайт 600 и представлена в виде одного хидера =)

С этим утверждением сложно спорить.

Ну да, можно в bochs всю машину по инструкциям отлаживать. И ещё масса способов уменьшить боль от анального секса.

Если пишешь для себя, тогда да, не стоит. Если пишешь в команде, то тебя будут всегда заставлять писать поддерживаемый код. Никому не интересно, что на CL писать изящнее, а на Erlang можно наплодить десятки тысяч процессов. Зато руководителю (если он не полный дебил, конечно) всегда заботит вопрос: «А кто и как потом будет это поддерживать»?

Рекомендую посмотреть подкаст Льва Валкина о том, как Perl и C++ были успешно заменены на Erlang и OCaml. В тиме, который раньше писал на PHP, Delphi, C++ и прочем мейнстриме.

Ты хочешь сказать, проект уровня firefox или postgresql писать очень легко? В юзерспейсе своих сложностей ой как хватает.

Firefox (xulrunner) внутри помойка, pg - очень хорошо организован. Зависит от того, кем и как проект организован. Тем не менее, отрицать, что кернель отлаживать не сложнее юзерспейса - ошибка.

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

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

Есть

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

> Итак, вернёмся к boost::mpl - это извращение?

несомненно, также как и boost::lambda и прочие костыли, именно поэтому латентные лисперы сначала прикручивают буст, а потом уходят на лисп

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

> несомненно, также как и boost::lambda и прочие костыли

Ну т.е. ведущие специалисты по C++ занимаются порождением всё новых и новых костылей (видимо всё остальное уже создали) и только на ЛОРе остались истинные ценители старины?

поэтому латентные лисперы сначала прикручивают буст, а потом

уходят на лисп



Хм, если вы про Александреску, то он ушёл на D.

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

> И ещё, сколько шаблонов нужно инстанцировать, что скомпилировать строчку

я насчитал пять - _Vector_base + vector + basic_string + allocator + __normal_iterator

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

> Ну т.е. ведущие специалисты по C++ занимаются порождением всё новых и новых костылей (видимо всё остальное уже создали) и только на ЛОРе остались истинные ценители старины?

переход на личности + упоминание «ведущих специалистов» - да вы троллите :) специалисты используют boost как полигон, жизнеспособные вещи попадают в стандарт, а костыли остаются костылями, странно что вы не в курсе

Хм, если вы про Александреску, то он ушёл на D.


а он разве латентный лиспер? или вы решили, что я так обозвал всех, кто пользуется бустом?

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

я насчитал пять - _Vector_base + vector + basic_string + allocator

+ __normal_iterator


Зависит от реализации, но число 10 выглядит более реалистично (все зависимости я уже подзабыл). Но это ведь было очень безобидное выражение. А сколько шаблонов надо раскрыть здесь:

std::vector<str::string> strings;
std::copy( std::istream_iterator< std::string >( std::cin ),
           std::istream_iterator< std::string >(),
           std::back_inserter(strings));

А ведь никакого «крутого метапрограммирования» здесь ещё не было, просто использование стандартных возможностей STL.

В реальном коде вложенность в 30 шаблонов возникает сама собой, даже в довольно обычном коде. Когда там «внутри» случаеся ошибка это полный атас. А возьмите частичную специализацию шаблонов с рекурсивными определениями в стиле Александреску, как бы совершенно нормальный приём...

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

> А сколько шаблонов надо раскрыть здесь:

В реальном коде вложенность в 30 шаблонов возникает сама собой, даже в довольно обычном коде


вы путаете вложенность с кол-вом

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

> жизнеспособные вещи попадают в стандарт, а костыли остаются

костылями, странно что вы не в курсе


Какие библиотеки из boost попали в стандарт? Какие остались «костылями»? Какова вероятность того, что когда-либо будет принят следующий стандарт C++? Подобное восприятие boost было справедливо в 98, а сейчас это просто демагогия.

или вы решили, что я так обозвал всех, кто пользуется бустом?


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

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