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 и иже с ним не предлагать.

★★★★★

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

>Но мне кажется что семантический анализ текстов и логический солвер это очень разные вещи.

Олимпиада разворачивается как раз вокруг солвера как простого и наглядного примера того, как на «любимом языке X» можно делать DSL.

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

[Компилировать динамически подгружаемую библиотеку, а затем подгружать ее. Помни, что на C и C++ написано большинство фантастически расширяемых вещей [..]

хехе, да уж решать динамические задачи таким образом - это «фантастика», точнее и не скажешь :)

Вы чего про расширяемость-то вспомнили, мы вроде за неё не говорим?

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

так что нет смысла сравнивать языки

А как же «что выбрать»? Я бы, например, ни за что не предложил С++ в качестве языка для поставленной задачи. Хотя да - пишут на нём, библиотек много, в том числе из сферы распознавания естесвенных языков.

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

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

http://www.mpprogramming.com/Cpp/

вот хорошая библиотека с «абстракцией на лету» и воможностью читать данные из файла

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

>Вы чего про расширяемость-то вспомнили, мы вроде за неё не говорим?

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

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

> А как же «что выбрать»? Я бы, например, ни за что не предложил С++ в качестве языка для поставленной задачи. Хотя да - пишут на нём, библиотек много, в том числе из сферы распознавания естесвенных языков.

если задача стоит ровно так как ее описали - то да, стоит взять пролог, но это не означает, что другие языки хуже - они просто не «заточены» под такой род задач

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

на CL из-за того что будет возможность использовать макро-средства и в рамках пролога

Зачем? В прологе своих макросредств полно.

P.S. Что-то постов много напостили, а кода плюсах до сих пор нет.

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

> кода плюсах до сих пор нет

да хрен с ними, с плюсами, уже. где хаскел? лисп? прочие Ъ языки «общего назначения»? пусть покажут разок «как надо».

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

>P.S. Что-то постов много напостили, а кода плюсах до сих пор нет.

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

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

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

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

А пока даже для этого класса на плюсах решения нет.

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

> Что-то постов много напостили, а кода плюсах до сих пор нет.

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

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

>А пока даже для этого класса на плюсах решения нет.

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

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

Просто скажи, будет от тебя код или нет? Все заинтересованные (я и автор треда) сделают выводы сами.

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

>Ну я же не поленился привести лучшее решение, чем нагуглил линуксфан.

Ах извини меня, что я поленился изучить пролог, чтобы привести решение не только на плюсах, где это якобы трудно и многословно, но и на прологе :D

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

> Ну я же не поленился привести лучшее решение, чем нагуглил линуксфан.

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

ahonimous
()

Let the Special Olympics begin!

Объект специальной олимпиады задачи вида {A танцует с Б (или супругом Б)}*, при этом танцевать со своим супругом запрещено. Нужно определить, кто с кем танцует и кто на ком женат. Тестовая задача:

Эд, Франк, Джордж и Гарри пригласили своих жен в вечерний клуб на танцы и для разнообразия решили, что каждый будет танцевать с женой другого. В результате Бетти танцевала с Эдом, Алиса - с мужем Кэрол, Дороти - с мужем Алисы, Франк - с женой Джорджа, а Джоржд - с женой Эда. Кто на ком женат? Кто с кем танцевал?

Правильное (и единственное) решение:

Эд женат на Дороти, танцует с Бетти
Френк женат на Кэрол, танцует с Алисой
Джордж женат на Алиса, танцует с Дороти
Гарри женат на Бетти, танцует с Кэрол

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

Зачем? В прологе своих макросредств полно.

Ну я могу сделать как интерпретатор пролога, так его компилятор CL - учитывая что компилятор CL генерирует весьма хороший код - это большой плюс. Ну и потом этот пролог - фактически мой DSL (о ста строках) и я могу его как угодно менять.

Семантически же код будет примерно таким как в вашем примере.

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

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

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

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

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

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

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

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

> Ну я могу сделать как интерпретатор пролога

А зачем он вообще нужен, если можно просто взять системы логики первого порядка, такие как PowerLoom?

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

Да не нужны тут никакие логика и пролог. Посмотрите внимательно на пример, там же просто термы кромсаются руками вот и всё.

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

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

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

насчёт «автоматическая генерация правил для семантического анализа текста» - в качестве грамматик будут использоваться грамматики Хомского или что-то посложнее?

фиг знает, пока разговора на эту тему ещё не было :)

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

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

Вы чего про расширяемость-то вспомнили, мы вроде за неё не говорим?

Про расширяемость начал прологер, который, якобы, вписал все правила в rules и сделал DSL

да не про расширяемость он «начал», как Вы выражаетесь, а про решение задачи в минимально таком виде, каком она будет стоять на практике

на деле захардкодил условие «никто не танцует с супругом/супругой».

в данном случае это уместно

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

Что-то постов много напостили, а кода плюсах до сих пор нет.

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

кто говорит А, должен быть готов сказать Б, иначе говоря, если кто-то кричит, условно говоря, что ваши липы фигня, всё делается на С++, и просто, должен быть готов обосновать свой ответ

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

А пока даже для этого класса на плюсах решения нет.

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

нет, программу придётся переписывать каждый раз - это неприемлимо

shty ★★★★★
() автор топика

Вот код на CL который решает задачу и печатает ответ (используется самопальный Prolog основанный на том что в PAIP):

(require :prolog)

(with-prolog
  (<- (танцуют Бетти Эд))
  (<- (танцуют Алиса ?x)  (женаты ?x Кэрол))
  (<- (танцуют Дороти ?x) (женаты ?x Алиса))
  (<- (танцуют ?y Франк)  (женаты Джордж ?y))
  (<- (танцуют ?y Джоржд) (женаты Эд ?y))
  (<- (танцуют ?y ?x))
  (<- (женаты ?x ?y))
  (let ((мужчины '(Эд Франк Джоржд Гарри))
        (женщины '(Алиса Дороти Кэрол Бетти)))
    (loop :for мужик :in мужчины
          :do (loop :for баба :in женщины
                    :do (progn
                          (?- (танцуют мужик баба)) (format t " (~A и ~A танцуют)~%" мужик баба)
                          (?- (женаты мужик баба)) (format t " (~A и ~A женаты)~%" мужик баба))))))
quasimoto ★★★★
()
Ответ на: комментарий от dmsh

Я, честно говоря, сильно сомневаюсь, что пролог написанный на cl будет работать со скоростью cl.

Вот самый простой транслятор http://norvig.com/paip/prologc.lisp из PAIP:

Форма Prolog -> Форма CL -> маш. код -> Profit!

1 стрелочка обеспечивается этим транслятором (там трансляция в примитивы вроде cons и if), вторая - компилятором CL (читай SBCL).

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

нет, программу придётся переписывать каждый раз - это неприемлимо

Лол, прологовскую тоже. В чем разница?

от лола слышу :) с чего Вы взяли что прологовскую программу придётся переписывать?

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

> кто говорит А, должен быть готов сказать Б, иначе говоря, если кто-то кричит, условно говоря, что ваши липы фигня, всё делается на С++, и просто, должен быть готов обосновать свой ответ

ну так и спрашивать надо персонально, а не обращаться ко всем и делать выводы относительно ЯП

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

фиг знает, пока разговора на эту тему ещё не было :)

Если на простых грамматиках делать, то я (используя код из PAIP) делал такую штуку:

(понять '(синий утрений дождь льёт на город))

((ПРЕДЛОЖЕНИЕ
  (ГРУППА-ПОДЛЕЖАЩЕГО (ОПРЕДЕЛЕНИЕ СИНИЙ) (ОПРЕДЕЛЕНИЕ УТРЕНИЙ)
   (ПОДЛЕЖАЩЕЕ ДОЖДЬ))
  (ГРУППА-СКАЗУЕМОГО (СКАЗУЕМОЕ ЛЬЁТ)
   (ДОПОЛНЕНИЕ* (ПРЕДЛОГ НА) (ДОПОЛНЕНИЕ ГОРОД)))))

Т.е. тут грамматика строго фиксирована, и на основе неё строится семантика текста. С другой стороны абсолютно не сложно как-то проанализировать текст, сгенерировать live-grrammar и разобрать текст (грамматику можно менять даже на ходу разбора). Если тут возникнут какие-то логически проблемы то можно использовать тот же пролог.

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

>от лола слышу :) с чего Вы взяли что прологовскую программу придётся переписывать?

Потому что правила захардкожены.

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

Ты не понял. Узким местом будет сам пролог (если, конечно, это будет полноценный пролог, а не наколеночное поделие за 15 минут), а не то, на чем он написан. И «маш. код» еще не означает автоматический «Profit!». Его так и не научились компилировать эффективно, насколько я знаю.

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

А зачем он вообще нужен, если можно просто взять системы логики первого порядка, такие как PowerLoom?

А если мне будут нужны высказывания над предикатами (логика второго порядка)?) И потом пролог простой.

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

И потом пролог простой.

О! Об этом почему-то редко вспоминают. Самое замечательное его свойство.

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

Слишком много всего позволяет, я думаю. Вот отпилили ему крылья, привинтили статическую типизацию (меркьюри) - вот только тогда показалось что-то, напоминающее производительность.

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

А что мне придется переписать в плюсах?

Я не знаю :) Мой мозг отравлен сами знаете чем :))

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

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

В CL средства построения DSL это язык в языке (т.е. ровно тот же CL только на мета уровне, как если бы аргементы шаблонов в С++ можно было обрабатывать произвольным С++ кодом), который работает в compile-time, и prolog - тоже компилятор в CL (может и не сверхэффективный было замечено. но всё таки). Ну и последний момент - ситуации когда необходимо писать интерпретатор не возникнет никогда - можно проводить трансляцию в CL, а также можно неограниченно расширять компилятор (два последних момента справедливы ещё и для GHC, но там не всё так прозрачно).

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

Это каким ещё образом?

Ну я сказал - так же как вводилась система высказываний (предикатов) над, так же можно ввести систему высказываний над этими предикатами. Вообще-то существует возможность строить мета-вычислитель для любой системы логики (metamath, напрмер, эта штука реализована даже на CL).

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

высказываний (предикатов) над -> высказываний (предикатов) над атомами, в более общем случае над wwf.

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

> Ну я сказал - так же как вводилась система высказываний (предикатов)

над, так же можно ввести систему высказываний над этими предикатами.


Я что-то не улавливаю связи с прологом. Как ты собираешься расширять пролог, что бы он стал способен работать на уровне логики второго порядка?

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