Как стать автором
Обновить
33
0
vseloved @vseloved

Пользователь

Отправить сообщение
Тот, кто захочет заменить способ хранения графа, конечно, не дурак, но что же, все недураки перед рефакторингом сидят и помечают все места, где надо не забыть заменить код? А в старый код ещё и вникать придётся. Какая-то monkey-work, честное слово. Достаточно где-то не заменить функцию, и ловим ошибки во время работы программы. Я же иногда даже просто беру и меняю тип данных. Всё. Далее мне компилятор сам выдаст все места, где надо поправить (тут, кстати, играет роль не только система типов, но и различие написания конструкторов и переменных и прочее), а там я уже решаю, нужно тут вникать, или сделать тривиальное изменение.

> Далее мне компилятор сам выдаст все места, где надо поправить
да, хорошо, когда есть такая возможность

> Разные вспомогательные функции в Haskell'е легко и просто описываются такой замечательной штукой, как undefined
ну, хорошо, что есть хоть элемент опциональности. Но вы зря приципились к слову вспомагательный. Может быть, что это важная часть, но мы пока ее не трогаем. Еще раз повторяю, зачем все сразу менять, если не уверен, что нужно. Или вы такой ситуации не допускаете?

> функция не меняет глобальных переменных и не пишет в лог.
Глобальные переменные и побочные эффекты — не единственные проблемы в программировании. В том, что вы говорите, конечно, есть свои плюсы, не спорю, но все равно это trade-off. Было бы неплохо, если бы решить мог сам программист, как вы считаете?
совершенно не обязательно на Python'е (или любом другом динамическом языке) тестировать типы. Типы все равно проверяются на этапе выполнения и самое страшное, что может произойти — Exception (это не С, где будет segfault), который можно отловить выше по стеку (вполне себе адекватная стратегия для многих программ). Т.е. семантика поведения все равно полностью определена, программа вполне может быть корректной, если она написана с учетом этого.

И, кстати, какой дурак будет передавать в функцию проверки двудольности графа нечисла? Точнее, скажу так, такой дурак найтись может, только он скорее всего будет не дурак, а тот, кто решит переписать существующую программу немного иначе: например, заменить числовые идентификаторы вершин на какие-то структуры. И разные вспомагательные функции (типа нашей bipartiteness-test) он пока не готов менять (хочет сначала проверить, как оно все храниться в базе будет). Не тут то было: чтобы проверить свой новый подход, ему придется еще преписать кучу всего в программе, где хоть как-то фигурируют эти вершины (ведь есть propagation типов, не так ли). И, если подход не подошел, усилия выброшены на ветер. Это называется coupling, а все говорят, что нужно стремится к de-couling.

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

А как может быть так, что программу на Python тестировать нужно меньше, чем на Haskell? Дело в том, что тестировать нужно не все, а то, что не до конца понимаешь, в чем не до конца уверен. В программе проверки двудольности на Python мало таких мест — все довольно таки очевидно,-- а вот в Haskell-варианте у нас 2 монады, монадные трансформеры. Хорошо, если вы это понимаете, себе можно доверять. А Васе Пупкину, который живет в Сибири, и написал этот код вы доверяете, что он в точности понимает логику работы этих монад? (Вы тут скажете: тут есть только 1 решение — правильное, остальные, просто, не скомпиллируются. Не согласен: как на счет нашего примера с неправильно заданным графом?) Тут мы и подходим к вопросу разработки больших систем…

Решение: дисциплина должна быть в головах, а в языках программирования — инструменты, доступные для использования.
про серебрянную пулю — это было замечание к «ощущению, что практически любой скомпилированный код будет работать сразу же» (работать то будет, но вот корректно ли? Python'овский код и компилировать не нужно — тоже сразу заработает ;)

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

И про тестирование забывать не нужно. И совсем не факт, что программу не Python нужно тестировать больше, чем Haskell'овскую. Как по мне, все зависит от уровня программиста, который ее напишет, и его понимания underlying концепций. (Хотя да, в среднем, наверно, для Python программы больше возможностей сделать ошибку, хотя и, наверно, больше возможностей попробовать разные варианты, поскольку программы, опять же в среднем, пишутся быстрее).

Тем более, что есть еще вопросы изменяемости программы со временем, интерактивной разработки, кодогенерации и т.д., на которые статическая проверка типов на этапе компиляции не дает хороших ответов. Но давайте о них не будем :)
Почитайте комментарии к заметке Льва — мы там и brainfuck обсудить успели.
А вам совет не моск ломать, а понять, что вы хотите сделать, и подумать, на каком языке это будет инетреснее всего для вас — так и выбирать. Эволюция эффективнее революции ;)
я там в комментариях привел пример плохих входных данных для Python версии ({1: [2], 2: []} Свойство симметричности для ненаправленного графа: если вершина А соединена с B, то B соединена с A), но глючить будут все (и Haskell, и Lisp, и Python).

Это я к тому, что проверка типов не гарантирует отсутствия ошибок даже на уровне типов, поскольку:
* подчас очень сложно описать реальный тип (т.е. исчерпывающий список ограничений) на языке системы типов. (Хотя есть, конечно, Тьюринг полная система вывода типов в Qi, но что толку, если программирование системы типов становится эквивалентной собственно решению задачи)
* даже если у нас будет язык для полноценного описания типов (см. Qi), нет возможности enforcement'а того, чтобы программист делал исчерпывающее описание

Короче говоря, type checker — хороший инструмент, но не серебрянная пуля в плане проверки корректности программы. Тестировать нужно и Haskell программу.
На счет типизации. Используется представление графа в виде списка пар вершина-список соседей. Вы уверенны, что программа будет правильно работать, если задать некорректно этот список (например, не соблюсти симметричность)?
в принципе, вывод о сложности кода касался непосредственно того примера, где сложность была излишня, как показывают решения на других языках.

на счет понятности языка: согласен, что он не должен быть понятен всем. Но все же останусь при том мнении, что регулярный синтаксис лучше ad hoc. В Haskell'e есть тенденция использовать очень специфичные нотации для кажой отдельной конструкции, а также довольно много иероглифов. Это приводит к тому, что не фулл-тайм Haskell-программистам сложно вникать в код, соответственно им это и не нравится (все естественно, не так ли?)

мой основной вывод: я понял, зачем существует язык Haskell :) Это, конечно, в шутку, но в каждой шутке есть доля правды.
забыл поставить кавычки возле слова «лицемерное» :)
по поводу того, какое лицемерное открытое ПО уже была статейка на itblogs: www.itblogs.ru/blogs/cio_anatomy/archive/2009/07/13/51045.aspx
ответ Руслана Шевченко (rssh) на счет *экономической* мотивации для опен сорс проектов сюда бы тоже подошел
так держать :p (http://artlung.com/smorgasborg/Invention_of_Cplusplus.shtml)
да, именно это.
Оказывается есть (почитайте rationale к тому же python-daemon). Особенно проявляются в связи с остановом, особенно когда начинаем иметь дело с потоками (например, попробуйте ка убить thread)
вы простите, конечно, мое занудство, но что будет делать при остановке прокси-сервер с кешем, сервер отчетов с БД, а сервер печати со спул-директорией?
и что, это никак нельзя обобщить? ресурсы сервера — это обычно дескрипторы (файлов, сокетов) — методы работы с ними стандартны. А какие еще ресурсы вы имеете в виду?
а в чем, по вашему, заключается особая специфичность в зависимости от задач?
а зачем учить плохому? ;)
(я этот тред затеял к тому, что обработка вызовов — далеко не самая морочливая и сложная задача, которая возникает при разработке серверов. Гораздо больше возьни с запуском/остановкой, контекстами и т.п. вещами — вот об этом и интересно было бы почитать.
sidenote: Тут, например, может помочь библиотека python-daemon, однако и она решает только часть проблем)
если это сервер, то как его остановить? ;)
а как вы справляетесь с тем, что в кириллической раскладки большинство стандартных аккордов не работает?
Странно, что ни в комментариях, ни в статье не прозвучало такое слово как «декоратор». А ведь именно о таком инструменте метапрограммирования, как я понял, здесь идет речь.

Во-первых Nemerle компилируемый язык программирования, поэтому отпадают механизмы из Ruby, Tcl и LISP.

Lisp, кстати, тоже компилируемый
По большей скорости программ, написанных на ФЯ, чем на С (и почему это возможно), недавно пробегала хорошая статья с длинным и обстоятельным обсуждением: scienceblogs.com/goodmath/2006/11/the_c_is_efficient_language_fa.php
Вкратце ответ: использование арифметики указателей во многих случаях не позволяет компилятору задействовать агресивную оптимизацию, потому что очень трудно определить области кода, в которых какие-то области памяти перестают быть использованы.

А в comp.lang.lisp тоже было хорошее обсуждение на тему реализации генетических алгоритмов на Common Lisp, которая в 26 раз быстрее Java реализации («The Java program turns out to be much slower than the Lisp
program. I was expecting it to be faster. To be precise, SBCL was 26 times faster than Java (SBCL: 16 minutes; Java: 7 hours)»). Вывод там был такой: в других языках для сложных задач часто приходится писать интерпретаторы, в то время как Lisp-среда за счет макросов позволяет работать с скомпилированным кодом для той же проблемы.
groups.google.com/group/comp.lang.lisp/browse_frm/thread/b25de73bbe5eb9ba#

Информация

В рейтинге
Не участвует
Откуда
Украина
Зарегистрирован
Активность