После выхода второго номера журнала "Практика функционального программирования" у меня состоялась интересная переписка с неким программистом, который очень любит писать на C.
Кульминацией этой переписки стало то, что он предложил мне следующее пари: я формулирую простенькую задачу, после чего мы оба реализуем ее - он на С, я - на Haskell. После этого в условие вносятся небольшие коррективы (моделируем поведение требований в реальном мире), а мы вносим коррективы в наши программы. Результаты сравниваются по скорости исполнения, объему потребляемой памяти, количеству строк кода.
Мой оппонент изначально был поставлен в неравные условия, т.к. я мог подобрать задачу так, чтобы ее было удобно реализовывать мне, и неудобно реализовывать ему. Впрочем, я постарался выбрать задачу так, чтобы ее решение не требовало каких-то узкоспециальных знаний. Фактически, мы занимались тем, что читали из файла и обрабатывали некую сложную структуру данных. (Детальное условие я тут не привожу, чтобы не "сбивать прицел" второй половине поста).
Моя первая версия активно использовала Data.Generics и библиотечные парсеры на их основе, поэтому выиграла в размере и читаемости кода, но пролетела по объему потребляемой памяти. Впрочем, мой оппонент настолько понадеялся на мощь C, что решил не использовать библиотечный qsort, а реализовать insertion sort самостоятельно. Это самым пагубным образом сказалось на производительности (LOCs - строки кода, память - в мегабайтах, время - в секундах):
Кроме того, выяснилось, что мой оппонент всячески "срезает углы" в погоне за производительностью. Например, функция сохранения обработанных данных в файл принимала, в числе прочих, числовой параметр, на который умножались определенные поля структуры перед сохранением - таким образом экономился один рекурсивный обход всей структуры данных.
В результате я тоже решил "срезать углы", и принести красоту кода в жертву скорости. Мой же оппонент взялся за qsort, и к вторые (финальная) версии нашего кода "финишировали" с такими результатами:
Я предполагал, что соотношение цифр будет гораздо сильнее не в пользу Haskell. Впрочем, меня по-прежнему можно было бы обвинить в предвзятом подходе к формулированию условий.
К чему я все это веду?
Существует классическая статья "Haskell vs. Ada vs. C++ vs. Awk vs. ... An Experiment in Software Prototyping Productivity", написанная в 1994-м году. За 15 лет многое изменилось, и, думается, многим было бы интересно прочитать подобную статью про положение дел сегодня.
В связи с этим ищутся:
1)Условия подходящей задачи (критерии см. ниже)
2)Желающие реализовать ее на Haskell/C+/Ocaml/Java/Scala/C#/... с тем, чтобы ваш код был нещадно сравнен с другими и опубликован для всеобщего обозрения.
Q:Зачем все это делается?
A:На других посмотреть, себя показать. В частности, чтобы люди имели возможность посмотреть на решения на других языках, и составить о них какие-то мнение.
Q:Чем не устраивает The Great Language Shootout?
A:Тем, что там отдается предпочтение "быстрым и грязным" решениям, которые всячески "срезают углы". Во-первых, в таком стиле пишется дай бог чтобы 5% от всех программ, во-вторых, людям, не знающим язык X, строго противопоказано смотреть на решения на языке X в Language Shootout - останется превратное впечатление.
Q:Как будут сравниваться решения, чтобы определить победителя?
A:Никак, т.к. победителей не будет. Будут приведена определенная статистика по всем решениям, без выводов.
Q:Какой тогда стимул участвовать?
A:На других посмотреть, себя показать :)
Какой должна быть задача?
1)Не заточенной под конкретную ОС (т.е. "Реализовать компонент, встраеваемый в Word" или "плагин для libpam" - не катит)
2)Не заточенной под конкретный язык/фреймворк/... (т.е. "получить список сигнатур методов всех объектов указанной сборки .Net" - не катит)
3)Если глубокие знания в предметной области дают решающее преимущество - это fail (т.е. "реализовать DES-CBC" - не катит)
4)Чтобы она не была из категории "мне не нужно, чтобы плац был чистый, а нужно, чтобы вы задолбались" (т.е. "распарсить XLS-файл, не пользуясь библиотеками" - не катит)
5)Задача не должна требовать много времени на реализацию (если это будут человеко-недели - никто за нее не возьмется)
Какой должна быть реализация?
1)Чтобы ее было не стыдно показать другим. В частности, чтобы решение на языке X не заплевали бы как кривое и неидиоматичное другие программисты, знающие язык X.
2)Идеально было бы давать две реализации: первую с ориентиром на "красоту", "образцово-показательность" и легкость поддержки/развития кода (т.е. пишем как пример кода, который будет прилагаться к резюме :), а вторую - "грязную и быструю".
3)Т.к. библиотеки - это неотъемлимая часть силы и популярности языка, библиотеками "общего назначения" (контейнеры, парсинг, ...) пользоваться можно и нужно
4)Но! Решение, которое свелось к исключительно к нахождению и использованию какой-то (узкоспециальной) библиотеки никому не интересно и рассматриваться не будет.
Выбирать подходящее условие будет жюри, представляющее апологетов всех течений и направлений, в том числе - включающее тех, кто критически отзывался о материалах, уже вышедших в fprog.ru.
Если у вас есть идея подходящией задачи и вы хотите ей поделится - напишите комментарий, а?
Кульминацией этой переписки стало то, что он предложил мне следующее пари: я формулирую простенькую задачу, после чего мы оба реализуем ее - он на С, я - на Haskell. После этого в условие вносятся небольшие коррективы (моделируем поведение требований в реальном мире), а мы вносим коррективы в наши программы. Результаты сравниваются по скорости исполнения, объему потребляемой памяти, количеству строк кода.
Мой оппонент изначально был поставлен в неравные условия, т.к. я мог подобрать задачу так, чтобы ее было удобно реализовывать мне, и неудобно реализовывать ему. Впрочем, я постарался выбрать задачу так, чтобы ее решение не требовало каких-то узкоспециальных знаний. Фактически, мы занимались тем, что читали из файла и обрабатывали некую сложную структуру данных. (Детальное условие я тут не привожу, чтобы не "сбивать прицел" второй половине поста).
Моя первая версия активно использовала Data.Generics и библиотечные парсеры на их основе, поэтому выиграла в размере и читаемости кода, но пролетела по объему потребляемой памяти. Впрочем, мой оппонент настолько понадеялся на мощь C, что решил не использовать библиотечный qsort, а реализовать insertion sort самостоятельно. Это самым пагубным образом сказалось на производительности (LOCs - строки кода, память - в мегабайтах, время - в секундах):
| LOCs | MEM max | Runtime, sec | |
| Haskell, v1 | 72 | 580 | 88 |
| C++, v1 | 861 | 55 | 383 |
Кроме того, выяснилось, что мой оппонент всячески "срезает углы" в погоне за производительностью. Например, функция сохранения обработанных данных в файл принимала, в числе прочих, числовой параметр, на который умножались определенные поля структуры перед сохранением - таким образом экономился один рекурсивный обход всей структуры данных.
В результате я тоже решил "срезать углы", и принести красоту кода в жертву скорости. Мой же оппонент взялся за qsort, и к вторые (финальная) версии нашего кода "финишировали" с такими результатами:
| LOCs | MEM max | Runtime, sec | |
| Haskell, v2 | 169 | 130 | 8 |
| C++, v2 | 950 | 54 | 5 |
Я предполагал, что соотношение цифр будет гораздо сильнее не в пользу Haskell. Впрочем, меня по-прежнему можно было бы обвинить в предвзятом подходе к формулированию условий.
К чему я все это веду?
Существует классическая статья "Haskell vs. Ada vs. C++ vs. Awk vs. ... An Experiment in Software Prototyping Productivity", написанная в 1994-м году. За 15 лет многое изменилось, и, думается, многим было бы интересно прочитать подобную статью про положение дел сегодня.
В связи с этим ищутся:
1)Условия подходящей задачи (критерии см. ниже)
2)Желающие реализовать ее на Haskell/C+/Ocaml/Java/Scala/C#/... с тем, чтобы ваш код был нещадно сравнен с другими и опубликован для всеобщего обозрения.
Q:Зачем все это делается?
A:На других посмотреть, себя показать. В частности, чтобы люди имели возможность посмотреть на решения на других языках, и составить о них какие-то мнение.
Q:Чем не устраивает The Great Language Shootout?
A:Тем, что там отдается предпочтение "быстрым и грязным" решениям, которые всячески "срезают углы". Во-первых, в таком стиле пишется дай бог чтобы 5% от всех программ, во-вторых, людям, не знающим язык X, строго противопоказано смотреть на решения на языке X в Language Shootout - останется превратное впечатление.
Q:Как будут сравниваться решения, чтобы определить победителя?
A:Никак, т.к. победителей не будет. Будут приведена определенная статистика по всем решениям, без выводов.
Q:Какой тогда стимул участвовать?
A:На других посмотреть, себя показать :)
Какой должна быть задача?
1)Не заточенной под конкретную ОС (т.е. "Реализовать компонент, встраеваемый в Word" или "плагин для libpam" - не катит)
2)Не заточенной под конкретный язык/фреймворк/... (т.е. "получить список сигнатур методов всех объектов указанной сборки .Net" - не катит)
3)Если глубокие знания в предметной области дают решающее преимущество - это fail (т.е. "реализовать DES-CBC" - не катит)
4)Чтобы она не была из категории "мне не нужно, чтобы плац был чистый, а нужно, чтобы вы задолбались" (т.е. "распарсить XLS-файл, не пользуясь библиотеками" - не катит)
5)Задача не должна требовать много времени на реализацию (если это будут человеко-недели - никто за нее не возьмется)
Какой должна быть реализация?
1)Чтобы ее было не стыдно показать другим. В частности, чтобы решение на языке X не заплевали бы как кривое и неидиоматичное другие программисты, знающие язык X.
2)Идеально было бы давать две реализации: первую с ориентиром на "красоту", "образцово-показательность" и легкость поддержки/развития кода (т.е. пишем как пример кода, который будет прилагаться к резюме :), а вторую - "грязную и быструю".
3)Т.к. библиотеки - это неотъемлимая часть силы и популярности языка, библиотеками "общего назначения" (контейнеры, парсинг, ...) пользоваться можно и нужно
4)Но! Решение, которое свелось к исключительно к нахождению и использованию какой-то (узкоспециальной) библиотеки никому не интересно и рассматриваться не будет.
Выбирать подходящее условие будет жюри, представляющее апологетов всех течений и направлений, в том числе - включающее тех, кто критически отзывался о материалах, уже вышедших в fprog.ru.
Если у вас есть идея подходящией задачи и вы хотите ей поделится - напишите комментарий, а?
(no subject)
Date: 2009-11-03 11:02 pm (UTC)(no subject)
Date: 2009-11-03 11:08 pm (UTC)(no subject)
Date: 2009-11-03 11:12 pm (UTC)(Сейчас придет
(no subject)
Date: 2009-11-03 11:17 pm (UTC)(no subject)
Date: 2009-11-03 11:25 pm (UTC)Наверное, каждый, кто пишет на C/C++ профессионально, вынужден был в какой-то момент свой кастом мемори аллокатор написать.
В двадцать первом веке.
Тьфу.
(no subject)
Date: 2009-11-03 11:33 pm (UTC)(no subject)
Date: 2009-11-03 11:37 pm (UTC)Только она другого уровня: не механическая (ещё класс, ещё темплейт, ещё один аллокатор), а математическая.
Ещё нужно учитывать, что большинство этих людей C/C++ знают очень даже на уровне, часто экспертном. Поэтому противопоставление хаскелистам сиплюсплюсных решений и аргументов забавно: аргументы из прошлой жизни. Ностальгия.
(no subject)
Date: 2009-11-03 11:42 pm (UTC)и радость мне доставляет изучение ассемблерных листингов скомпилированного кода и бюджеты за мою работу.
мы с вами думаем на разных языках.
(no subject)
Date: 2009-11-03 11:50 pm (UTC)Так что, опять же, все эти задачи я понимаю, знаю, и люблю.
... плюс теперь хаскель. Это позволяет лучше потом на си писать.
(no subject)
Date: 2009-11-03 11:56 pm (UTC)(no subject)
Date: 2009-11-03 11:58 pm (UTC)(no subject)
Date: 2009-11-04 12:10 am (UTC)(no subject)
From:(no subject)
Date: 2009-11-04 05:11 am (UTC)(no subject)
Date: 2009-11-21 07:45 am (UTC)Это неверно. Распространённые реализации malloc делают практически всю работу в юзер-спейсе, и делают это SMP-ориентированно, cache-friendly и с кучей диагностических фишек, которые сама по себе OS обеспечить не может.
Но если действительно что хитрейшее - то возможность написать свой аллокатор может быть очень кстати.
Никто не спорит с этим.
Почитал все обсуждение - это да, ФП программирование применимо к узенькой предметной области.
К какой?
(no subject)
Date: 2009-11-21 10:03 am (UTC)2. говорить что в 21ом веке обязательно нужно писать свой аллокер - потому что их написано тьмы.
Внутренне противоречивый абзац. Если бы malloc не был медленным, то в 21м веке свои маллоки бы не писали. Более того, конечно не должно нужно писать свой маллок в 21 веке — но приходится — см. мой опыт в Cisco несколькими постами выше.
Прикладная математика, олимпиадные задачи, утилиты парсинга/генерации
А это ничего что с FP программируют телефонию (Erlang)?
Ничего, что с FP программируют веб сервисы (Facebook Chat — Erlang, Twitter — Scala)?
Ничего, что процессоры моделируют и проектируют (thesz — это ведь не совсем прикладная математика, олимпиадная задача, и утилита парсинга)?
не первый месяц слежу за блогами ФПшников и форумными дебатами вокруг ФП - адептам ФП видней, а они только такие задачи и "решают"
Смотри второй выпуск http://fprog.ru/, там начало серии статей про применение FP в реальных проектах.
(no subject)
Date: 2009-11-21 11:23 am (UTC)1. Функциональные языки менее распространены, чем нефункциональные. Это правда, это исторически обусловленно.
1.1. Скорость выполнения, например, просасывала по-полной императивным языкам. Но каким языкам? Она просасывала языкам типа C, которые сейчас явно не в фаворе. А те языки, которые в фаворе (Java, C#) отличаются от современных функциональных языков на какой-то эпсилон.
1.2. Уровень абстракции, быстро достигаемый с помощью функциональных языков, был не нужен в восьмидесятых годах. Тогда ещё занимались инфраструктурой, обслуживанием машин (там C рулил), а не высокоуровневой аналитикой.
2. Функциональные языки применимы только в узких областях. Нет, это неправда.
2.1. Они применимы в гораздо более широких областях, чем принято считать. Впрочем, количество проектов в этих областях у функциональных языков будет необходимо меньше, чем количество проектов в тех же областях, делаемых на императивных языках. Смотри пункт 1, почему: чисто статистически, менее распространённый язык будет меньше представлен в какой либо, выбранной наугад, области.
2.2. Функциональные языки вертикально масштабирются до самых требовательных применений. Обратим внимание: несмотря на то, что они менее распространены, во почти всех областях, где они используются, они достигают самых высоких мест по важным критериям: способности выдерживать нагрузки, способности инженеров справляться с объемом получившегося кода, etc. Это показывают примеры с Facebook, Twitter, Amazon.
3. FP никто не использует в России. Это неправда. Источники были уже приведены. Если после этого возникает вопрос, почему их так мало, то, логично, смотри пункт 1, про распространённость языка.
4. Россия — третий мир, и наиболее рутинные задачи будут спускаться сюда, в аутсорс, в существенной степени определяя рынок и используемые технологии (PHP, Java, etc). Кто это сказал? Кто здесь? Может и верно.
5. Наш проект (4+ mln $ финансирования, двадцать программистов в России) использует OCaml + Erlang в качестве основной рабочей лошади.
6. Даже если FP где-то рулит, то использовать нужно мейнстримные языки. Ну это кому как — мне интересно не соревноваться с толпой программистов на Java или C#, пишущих очередные опердени. А на более экзотических задачах, где стандартные библиотеки уже не спасают, функциональные языки имеют преимущество. Поэтому выбор — ориентироваться на мейнстрим, или ориентироваться на странные платформы — он целиком индивидуальный.
Заодно отвечу про Erlang и Scala.
"Мог быть - каким угодно" — не мог: немутабельность состояния — это существенная фича для эрланга, она идёт рука об руку с многопоточностью, поэтому императивным он быть не мог. Императивный эрланг называется Go, и сосёт.
Если Scala не рассматривать как функциональный язык, или Erlang не рассматривать как функциональный язык, мы получим, что распространённый функциональный язык всего один: Haskell.
Потому что и в LISP, и в OCaml существенный блок их реализации полагается на сайд-эффекты и императивные алгоритмы и структуры данных.
Рассматривать же FP == Haskell — это слишком узко, чтобы такая точка зрения была полезной.
(no subject)
From:(no subject)
From:Re: ...continue (2/2)
From:Re: ...continue (2/2)
From:Re: ...continue (2/2)
From:Re: ...continue (2/2)
From:Re: ...continue (2/2)
From: (Anonymous) - Date: 2011-08-18 12:10 pm (UTC) - Expand(no subject)
Date: 2009-11-21 02:01 pm (UTC)>И сколько сотен программистов занимаются моделированием процессоров? Или, ужас - тысяч! Какая широкая предметная область :)
Каждая производящая процессоры или системы на кристалле компания вынуждена держать штат моделирующих программистов. Даже, если пользуется внешними ядрами процессоров. Таких компаний десятки, если не сотни. Самих систем SoC тоже - тысячи, если не десятки тысяч. По программисту на систему, вот и рынок в тысячи программистов. ;)
>Мало того, у меня вообще ощущение что thesz - единственный профессиональный програмист на ФП во всем рунете.
Есть и ещё, есть. ;)
Нас много. ;)
(no subject)
Date: 2009-11-03 11:31 pm (UTC)http://www.cs.umass.edu/~emery/pubs/berger-oopsla2002.pdf
После этого, впрочем, был вынужден делать ДВА general-purpose аллокатора памяти для Cisco. Наверное, чужой опыт меня не убедил.
(no subject)
Date: 2009-11-07 08:45 pm (UTC)(no subject)
Date: 2009-11-08 02:19 am (UTC)(no subject)
Date: 2009-11-08 12:17 pm (UTC)От отладить еще один malloc, верю, откажешься, ибо ты уже это сделать. А вот от того, что ты еще не сделал?
(no subject)
Date: 2009-11-07 08:41 pm (UTC)Да вы что. Он из коробки, на маленьких кусочках делает brk. И как вы хотите делать free? Если подойти к процессу с фантазией, то можно очень сильно раздвинуть сегмент данных.