Pull to refresh

Comments 222

Не согласен. В статье я ИМХО вижу лишь психологические проблемы автора (его почему-то деморализует знание haskell/python) + использование функциональных идиом там, где их использовать не нужно. Дело в том, что знание ФП действительно улучшает программиста даже если нужно программировать на императивном языке (мне например нередко приходится писать на чистом C). Ты знаешь альтернативные подходы, можешь разработать, например, более продвинутую _архитектуру_. Но использовать анонимные делегаты в C# там где на _данном_ языке можно просто записать цикл - это, извините, клиника.
Плохой и непонятный код можно написать на любом языке ;)
Всё зависит от того, кто этот код пишет.
И, кстати, Си тоже "развращает" :D
После него тяжко нормально писать на ассемблере =)))
хм, а я воспринимаю C как кросс-платформенный ассемблер

imho это не очень высокая абстракция над классической шарманкой Тьюринга :)
Это шутка была ;)
(см. смайлики =)
Как бы понял :)
К сожалению ничего лучшего чем "шарманка Тьюринга" не было реализовано в железе. Исключая дорогие и бесполезные прототипы...
А так почти любой популярный ЯВУ можно рассматривать как "абстракцию" языка программного автомата Тьюринга. Различие - степень абстракции...
UFO just landed and posted this here
Вы совершенно правы! =)
Немногие эту разницу чувствуют ;)
за что минус? кто-то на свой счет принял?
По мне так, приведенные вами примеры кода лишь илюстрируют ущербность синтаксиса Python, по сравнению с C# и Java. Скажу сразу, с питоном знаком весьма и весьма плохо. Дружба же с c# и java длится уже не первый год, так что возможно я ошибаюсь. Привидите побольше примеров.
мопед не мой (это хабраперевод), но могу предположить, что вы мыслите на C#/Java, поэтому и код на Haskell/Python кажется вам инопланетным

примеры вряд ли что-то изменят
Простите, но одна строка - это не пример.
Для того, чтобы понять язык примеров недостаточно. Нужно попробовать что-нибудь написать на нём.
C# и Java тоже ущербны - если не в синтаксисе, так в другом. Каждому языку - своё предназначение и спорить о том, какой язык лучше - бесполезно ;) Нужно просто брать и использовать тот язык, который лучше всего подходит к задаче.
(всё ИМХО ;)
В этом, по-моему, и состоит проблема Haskell-еподобных языков. Код на императивном языке можно прочитать, не изучая язык, не пробуя писать на нём что-нибудь (например, я могу спокойно читать Java, зная C++ и C#). Я тридцать раз подумаю, прежде чем пустить код на Haskell в продакш — кто его поддерживать будет, если гений, который писал на нём, уволится? Даже потом переписать на что-то понятное — целая проблема, потому что просто прочитать код очень тяжело.

Пример на Питоне (который "\n".join(...)) — меня просто убил. :) Как из этого вывести идею алгоритма — собрать текст из строк, разделённых \n — мне, например, ОЧЕНЬ неочевидно.

То есть, я охотно верю, что идеология этих языков очень сильная и логичная, но как их применять на практике (в смысле, не в Google) — не понятно.
Я начал изучение Python'а с того, что мне необходимо было переписать чужой код - относительно большую и сложную программу (добавить в неё новый функционал).
Сел и переписал, попутно обращаясь к руководству по языку - никаких проблем не возникло. С тех самых пор и "подсел" на этот язык, и до сих пор не жалею.
В то же время параллельно пишу на Си, PHP, Паскале, Перле, JavaScript'е и (иногда) на ассемблере (AVR). Ни разу не возникало затруднений =)

P.S. Мне очень нравится одно высказывание, которое я где-то (уже не помню где) прочитал: "Хороший программист должен раз в год учить новый язык".
Ой, а на паскале-то зачем?
Книжка программист-прагматик, авторы Хант и другие
да на Питоне можно и лучше написать, и на Haskell можно лучше — просто у автора статьи было мало опыта в этих языках, на самом деле

развернуть "обратную" нотацию в последовательную в таких языках это ни разу не проблема
>Пример на Питоне (который "\n".join(...)) — меня просто убил. :) Как из этого вывести идею алгоритма — собрать текст из строк, разделённых \n — мне, например, ОЧЕНЬ неочевидно

Это значит лишь, что вы вообще не знаете Хаскель или Питон. Я Хаскель изучал довольно поверхностно, Питон в глаза не видел, но все три примера понял сразу, хотя с нотацией >>> на Хаскеле тоже не знаком.
А вот как раз на Шарпе и не понятно, что же делается. Видно цикл, в котором вызывается метод, потом идет проверка и конкатекация. А что же это такое в целом - вы в голове додумываете сами. Просто мы настолько к этому привыкли, что делаем это автоматически.
>>Просто мы настолько к этому привыкли, что делаем это автоматически.
ну и что?
Да нет - просто код на императивном языке легко прочитать (там же никаких адстракций нету - голые простые действия), код на Python или Haskell проще понять - а уж дальше решайте что вам нужно...
"Код на императивном языке можно прочитать, не изучая язык, не пробуя писать на нём что-нибудь"
Это потому, что вы знаете один из императивных языков. Точно так же, зная один функциональный язык, проще понимать другие такие же.

"Как из этого вывести идею алгоритма — собрать текст из строк, разделённых \n — мне, например, ОЧЕНЬ неочевидно."
Исключительно вопрос привычки. Через небольшое время практики такие конструкции станут для вас прозрачными.

"но как их применять на практике (в смысле, не в Google) — не понятно."
То есть Гугл и Яндекс практикой не занимаются, только теоретизируют? :))
Если следовать этой логике, то не надо было вообще никаких языков, кром кода машинного придумывать. Каждый новый язык программирования только добавляет энтропии в хорошо устаканенное поле деятельности программиста.

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

Закажите себе SICP или почитайте Dive into Python. Полистайте странички на LambdaTheUltimate. Расширение кругозора никому никогда не мешало...
UFO just landed and posted this here
Попахивает статьей для девочек про буддизм где-нибудь в космополитене.

Можно было написать еще: Что вы паритесь? Лучше просто создать свою фирму размером с майкрософт (как Гейтс) и тогда за вас будут писать все программы ваши собственные крутые программисты.

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

Ставлю большой и жирный минус. Во-первых оффтопик, во вторых дешевый понт, в третьих просто глупо.
А по-моему, это стеб был. Зря вы так всерьез восприняли :)
Вы его остальные посты видели? Ребёнок с накладной бородой мудреца.
Во-первых, метод, по уму, должен был называться getDescription()

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

Такое чувство, что этот недоделок получил задание укатать Java и C# в пользу Haskell. Ничего умнее, кроме как выдернуть пару сложных конструкций, написать несвязанный бред, расчитанный на незнающих язык людей, он не придумал.

Видимо предполгается, что менеджер высокого звена остановится на фразе ...корявая глиняная хибара в сравнении с элегантным шпилем кода на...

Как говорится - фтопку!
Хаскель и Питон возможно отличные языки, но из статьи скорее следует обратное.
>> Во-вторых, какого хрена этот чудик ухитрился впереть сюда генерикс и делегаты

вообще-то это была иллюстрация "как не надо делать в C#" — статью, вы, похоже, не читали (много букв?)
Похоже, что наоборот, я статью не только что прочитал, но ещё и подумал о том, что там написано. В отличие от самого переводчика, который повёлся на зомбирующий стиль статьи.
Статья написана в стандартном рекламном навязчивом стиле, смысл которого состоит в том, что неважно хорошие (правильные) или плохие примеры приводятся. Главное в ней, что возле слова C#, мы постоянно видим эпитеты в духе: многословный, уродливый, кривой, ничего не делает... Что и отпечатывается в памяти.

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

А уровень автора виден вот по этой фразе: ...применение принципов функционального программирования привело бы меня к использованию лишь статических методов, не используя instance-методы, везде где это только возможно, избегая всего, что изменяет состояние или даже потенциально способного его изменить. Я бы использовал лишь простые 'тупые' типы данных, отделяя алгоритмы от них...
Что по сути означает – уходим дескать от высокоуровневых абстракций и начинаем акцентироваться на колупании в потрохах. Это типа достойный уровень программирования в 21 веке. За травой, потерян лес. :-)
>> В отличие от самого переводчика, который повёлся на зомбирующий стиль статьи.

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

уровень автора, как программиста вообще никак не сказывается на интересности статьи — человек взял и изучил Haskell, от чего у него случился культурный шок

он попробовал с наскоку перенести свой новообретенный опыт в C# — ничего не вышло, о чём он и написал

я больше чем уверен, что такая же психологическая проблема настигнет любого с более-менее похожим проф. бэкграундом (C++/Java/C#) после осмысления FP

а вы пытаетесь что-то там увидеть между строк (зомбирующий стиль, etc), ну так давайте, раскройте нам еще одну теорию заговора :D
полностью согласен, зачем пихать функциональный стиль во все дырки?!! в примере 2 достаточно было написать тривиальный цикл и выделить его в метод (с понятным названием), это было бы более читабельно, чем приведенный питоновский и хаскелевский код.
а что, в статье где-то говорится о том, что надо пихать функциональный код "во все дырки"?

цикл там парой строк ниже приведён

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

Да цикл приведен, но горе-читатель не заметил что он почему-то назван нудным? Нудность эта фиктивная, пользы от функциональщины в этом примере - почти нуль.
И питоновская и хаскелевская строчка кода нуждаются в комментарии.
Для кого и зачем? Если вы знаете функциональное программирование хоть на каком-то уровне (даже не конкретный язык, а функциональное программирование вообще), то любая из этих строк ничуть не сложнее для понимания чем код на C#. Достаточно обернуть это дело в функцию с "говорящим" названием и всё. Как вы бы с кодом C# сделали. Чего там комментировать-то?
само собой, если "это дело" обернуто в функцию с нормальной мнемоникой, то я, скорее всего, даже заглядывать в нее не стану!
да, но ведь эта функция где-то используется — и используется в точно таком же императивном контексте

эдак можно заявить, что "я оберну всю программу в функцию doEverything и даже заглядывать в неё не стану!"

станете :)
прошу прощения, перепутал горе-читателя с горе-переводчиком :-)

P.S. вместо того чтобы минусовать лучше бы кармы добавили, а то комментировать лень ;-)
добавил, комментируйте еще

дело в том, что помимо того, что код надо читать, его надо еще и писать - и то, что я на C# заверну 'нудную' реализацию в функцию с читабельным именем никак мне не облегчит саму задачу написания кода

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

кстати и читается цикл, по моему скромному мнению, как ни странно легче, просто в силу того, что этот микропаттерн сидит глубоко в подкорке
UFO just landed and posted this here
ба! какие люди! человек-жираф!!! :)
>>Во-первых, метод, по уму, должен был называться getDescription()
В стилистике C# GetDescription()
ужасающе

вообще-то это была достаточно саркастическая статья
там ещё Update в конце есть в оригинале

но кривым переводом конечно всё убито напрочь
эхх
я не стал переводить Update, незачем разжевывать очевидное

то был ответ автора некоторым личностям из комментариев к оригинальной статье
Хаскель портит мозг. Оба моих знакомых, кодящих на хаскеле - психи.
А ещё у нас на ушах растут типобезопасные отростки, руки вечно волосаты от безостановочного карринга, вместо энтера у нас на клавиатурах символ
Да что ж такое, хабра не схавала юникодную лямбду ):
В общем вместо энтера у нас на клавиатурах лямбда, а по выходным мы сворачиваемся в хвостовую рекурсию.
Хабр отлично кушает все символы и λ в их числе - это у вас, наверное, нежелание, неумение учесто то, что работает он таки в windows-1251, а не в Unicode...
Издержки utf-ной локали (:
Всё, пойду Haskell учить! Тоже хочу в хвостовую рекурсию сворачиваться. А то всё на питоне да на питоне... :-)
Вы демонстрируете на удивление слабое владение логикой.
Все ручки пишут синим. У меня две на столе лежат - они пишут синим.
Не ищите логики в сумасшедшем доме...
Я знаю некоторых "психов", на хаскеле пока не программируют, но склонность к функциональным языкам имеют.

Большинство людей никогда не смогут программировать, большинство программистов никогда не поймут принцип функционального программирования.
И ничего страшного. Кому-то же нужно и формочки программировать. Сколько народу умеет проектировать автомобили? А сколько на них ездит? Не может человек понять функционального программирования - не надо, пусть занимается не программированием, а чем-то другим... Но зачем ради них хороших программистов мучить?
Тут ведь проблема в теории о "непогрешимости миллиона лемингов". Если большинство не сможет писать, то и элита не сможет - не может код существовать сам по себе, без поддержки того самого миллиона лемингов код никому не нужен.

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

Именно это и происходит в Haskell, Common Lisp, Scheme и даже Prolog. Вы читаете программу и видите «что» она делает, на Java, C# и т.д. вы видите «как» она что-то там делает. Понятным миллионам этот подход не стал.
Эту статью писал профессиональный разработчик? Если да, то заявления в духе "Потом эти методы вызываются фреймворком в неясном и сложном порядке (да, это кошмар в отладке)" выглядят очень-очень странно. Любая более-менее внятная книжка об ASP.NET, не говоря уж об MSDN, имеет главу, в которой рассматривается жизненный цикл страницы в ASP.NET. По-моему, первое дело профессионального разработчика — изучить инструменты, с которыми он собирается работать, а не тратить время на перевод конструкций одного языка в другой и сокрушаться по этому поводу.

Далее, если C# так противен, что "аж кюшать не могу", то, возможно, стоит использовать тот же IronPython или Haskell for .NET, благо платформа позволяет? А уж, если и .NET с его "неясным и сложным порядком" сердцу не мил — то зачем задерживаться в Microsoft-шопе? Почему разработчики, использующие C++ и C# идут в Microsoft-шоп, а не в Haskell-шоп, где они могли бы часами жаловаться на непонятность Haskell?
да, в общем-то, это проблема любого IoC — отлаживать сложнее, т.к. flow не так очевиден

исходя из моего собственного опыта - отлаживать функциональную программу намного легче, да и отлаживают там не step-by-step отладчиком, а в REPL стиле (read-eval-print-loop)

IronPython и Haskell для .NET - это не промышленные решения и приемлемы лишь для энтузиастов-одиночек или очень маленьких команд, поэтому приходится использовать mainstream
Собственно, наличие IDE не означает, что методы отладки, отличные от step-by-step, отменяются. В большом проекте больше на логи полагаешься.
Логи и step-by-step - это одного поля ягоды. Функциональные программы изначально разделены на отдельные части и их можно дёргать более-менее в любом порядке. Так что вам ничего не стоит написать функцию, покидать в неё несколько примеров, передать её в другую функцию, которая покидает в вашу функцию каких-нибудь данных, etc. Время отладки уменьшается в разы.

Собственно последняя мода (unittests и mockups) пришла в императивные языки из функциональных - только там, как правило, все необходимые для отладки средства есть прямо в языке и не требуют специальных извращений. Типичный пример: в C# чтобы можно было использовать mock'и вам нужно разделить класс на интерфейс и реализацию, сделать две реализации интерфейса и в конструкторе класса, использующего ваш добавить дополнительный параметр - но это всё окупается (или по крайней мере нас стараются в этом убедить)... а как это делается в функциональном языке? Очень просто: загружаем класс, который нужно за'mock'ить, меняем прямо в нём пару методов (которые в сеть ходят и т.п.), загружаем класс, который нужно тестировать, смотрим на результат. Что может быть проще?
В большом проекте со сложной логикой есть смысл обратить внимание на test driven development.
Именно поэтому я и пишу на самом Питоне, а не пытаюсь изображать Питон на С. Жаль, что у вас нет такой возможности.
Програмироввание - самое результативное достижение левого полушария.
Всё было бы хорошо, если бы его можно было бы чем-то уравновесить.

Но возможен вариант, что прораммист в силу сильного левого отклонения (я) просто не в состоянии увидеть уравновешивающий фактор.
А не думали ли Вы, что путаете понятия "программист" и "кодер"? Я считаю что программист - художник, а кодер - рабочий (возможно инжинер).
каждый кодер - программист, и каждый программист - кодер

не нужно разделять неразделяемое

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

Программист — это который программирует. Остальное — ваши фантазии.
Вот только хотел взяться за Питон...
Теперь вижу себя только водилой трамвая =)
Не обращайте внимания на подобные статьи.
Изучайте Питон (и не только Питон =)
Даже если он не будет Вашим основным языком, вреда от того, что Вы его изучите уж точно не будет ;)
Спасибо, главное в голове поселить его подальше от Java и PHP. А то запилю потом себя как автор статьи :)
согласен. учится, учится и еще раз учится.
питон может показать очень изящные решения многих задач
вообще, если уж ломать шаблоны, то ломать до конца — т.е. сразу взяться за Haskell (там нет возможности писать код так, как вы делали это раньше)
Собственно потому до него мало кто и доходит. Лучше всё-таки Python - и применить его больше где можно и писать можно на смеси Python и C. А Haskell или erlang - они совсем отделены от "основной массы".
Может просто не забывать про замыкания, тогда можно написать что-то вроде

StringBuilder res = new StringBuilder();
mylist.ForEach(delegate(TestClass t)
{
res.Append((t.getString().Length != 0) ? t.getString() + "\n" : "");
});

Согласен, не совсем функциональный стиль, но как-то лучше того что написал автор статьи.

Если хочеться в функциональном стиле, то надо один раз написать что-то вроде

public delegate T1 AccumulateDelegate<T1, T2>(T1 prev, T2 value);

static T1 Accumulate<T1, T2>(IEnumerable<T2> l, T1 init_val, AccumulateDelegate<T1, T2> functor)
{
T1 res = init_val;
foreach (T2 t2 in l)
{
res = functor(res, t2);
}
return res;
}

И можно писать

string res2 = Accumulate(mylist, "", delegate(string prev, TestClass tc)
{
return prev + ((tc.getString().Length != 0) ? tc.getString() + "\n" : "");
});


И еще про питон, как функциональный язык. Лямбда функции там могут состоять только из одного выражения =(
Эхх. Отправил комментарий, и понял, что написал по сути тот же foreach =(
Больше не буду умничать за полночь.
нет, вы написали классическую higher-order функцию fold
а foreach - это совсем другие тапки, в функциональных языках этого не существует (т.к. понятие foreach неприменимо в функциональной терминологии)
foreach - это почти map. Не полностью идентично, но ближайшая аналогия, ИМХО.
Может быть вам стоит попробовать сочетать языки? Например Си и Питон замечательно уживаются через Python Extensions. Все что хочется писать быстро и красиво делается на Питоне, а узкие места выполняются в виде расширения на Си.
проблема в том, что когда работаешь на "дядю" - "дядя" (project manager) не захочет иметь такой фарш в проекте, а если еще и текучка кадров высокая..
Иногда можно забороть "дядю" следующим аргументом: "Вот можно сделать эту фичу за день на Питоне или за неделю на Си. А когда понадобится что-то менять в коде, каждое изменение займёт опять день, если фича была написана на Питоне, или опять неделю, если на Си." Это не всегда правда, это не всегда поможет убедить "дядю". Ну и, конечно же, неплохо бы при этом чувствовать разницу между "потому что так лучше для проекта" и "потому что мне на Питоне прикольнее", чтобы не выглядеть фанбоем...
вот такую строчку на питоне
"\n".join(foo.description() for foo in mylist if foo.description() != "")
можно было написать так
"\n".join(foo.description() for foo in mylist if foo.description())
да и списковое включение - не совсем функциональный стиль. в фп языках здесь скорее было бы map и filter.

по теме - если думаете на питоне/хаскеле - пишите на них. питон замечательный язык, не нужно себя насиловать. если насилуют обстоятельства - меняйте место работы. питон-программисту найдем хорошее место.
Мне кажется, что выражения "if (value)" непонятны. Лучше использовать "if (value!="")"
Так пишут большинство программистов еще с C, так что должно быть понятно
UFO just landed and posted this here
если автор что-то и фетишизирует, то декларативность

когда вы пишете цикл, вы говорите, как нужно сделать

когда вы пишете list comprehension или даже map/filter (как в примере) — вы говорите, что нужно сделать

семантика разная, а не внешний вид
для иллюстрации, тот же код на Haskell, но приправленный библиотекой Arrows:

myDescriptions = delete "" >>> List.intersperse "\n" >>> concat


это практически человеческое объяснение того, что нужно сделать:

myDescriptions = вырезав пустые, разбавить ньюлайнами, потом всё склеить


сравните это с унылым циклом:

завести пустой аккумулятор

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

возвратить аккумулятор


Оккам был бы недоволен
упс, забыл про дескрипшены :)

myDescriptions = map description >>> delete "" >>> List.intersperse "\n" >>> concat
абсолютно тот же самый "как" а не что. Просто синтаксис позволяет простые случаи "свернуть"
Может, вы задание не читали?
>Мне нужно было склеить все непустые description'ы, разделив их переносами строки.
И сравните с
map description >>> delete "" >>> List.intersperse "\n" >>> concat
описания - непустые - разделив переносами - склеить
Где тут "как"?
Видимо вы не различаете "как" и "что". А отличие простое: если вы говорите "как", то компилятор/интерпретатор имеет кучу свободы в своих действиях. Если говорите "что", то у него не остаётся никакой свободы - он тупо делает что сказали. Скажем интерпретатор Haskell легко может ускорить вещеописанную конструкциюю на восмиядерном процессоре (конечно если у вас объектов много - но это уже его задача понять стоит это делать или нет). Ваш же цикл в C# задаёт все операции жёстко и накакой особой свободы там нет (ну да компилятор может использовать EAX или EBX - большое дело).
Всё как раз с точностью до наоборот. Если вы говорите компилятору 'как' то именно так он и делает. И свободы у него нет. А когда говорите 'что', то он сам решает как это сделать. Имея полную свободу. В этом и отличие императивных языков от декларативных. Декларативные вроде как нагляднее, но это пока человек способен чётко постулировать одной фразой что он хочет получить. Это, кстати, не так и просто. Хороший пример - язык SQL. Пока вы просто командуете что вам нужны поля такие-то и такие то, то всё гуд и в шоколаде. А вот как только вам нужно сделать сложную обработку, то декларативный запрос оказывается написать куда как сложнее. Почему и появился язык хранимых процедур. Уже императивный по своей сути.
UFO just landed and posted this here
>> ... распараллеливание вычислений, а тем более логики задача очень сложная и нетривиальная

поистине нетривиальная она лишь в императивных языках
>> не смотря на всю «оптимизацию и производительность», Eclipse тормозит, сколько бы маркетологи от Sun не рассказывали как «восхитительно эффективна Java»

Eclipse тормозит потому что он сложен — включая сложность Java и библиотек на которых Eclipse построен

вот у меня Visual Studio — тормозит куда сильнее эклипса, а написано оно — вниимание — на C++

rotfl?
>>... к тому же в соревновании по производительности «интерпетаторы vs. компиляторы»

вы напрасно прицепились к слову «интерпретатор» в комментируемом посте

к примеру, Haskell-код можно интерпретировать, как код на C — что и будет тем самым «компилятором» (кстати, рекомендую почитать работы Футамуры — Futamura projections — для понимания математической связи интерпретаторов, компиляторов и частичных вычислений)

для функциональных языков (и Haskell, в частности) есть сильно оптимизирующие трансляторы в императивный код (и их research до сих пор ведется), обычно используется трансляция в C — с последующим скармливанием его gcc

к примеру, программы на строгом ML после трансляции в C не уступают в производительности "рукописному" C-коду даже в числодробительных задачах (ML это как C в функциональном мире)
Отлично я понимаю. Просто чтобы кто не говорил а интерпретатор за вас думать не будет. В данном случае он тупо создаст мап, удалит пустое, разбавит и склеит. по шагам. где тут "как"? То что синтаксис позволяет следовать фразе на русском... ну чтож, позволяет. Только не разу не видел чтобы обратное было проблемой
>> В данном случае он тупо создаст мап, удалит пустое, разбавит и склеит.

в данном случае он может частично-вычислить выражение и преобразовать хвостовую рекурсию в цикл — получится такой же императивный код, как в примере с C#
UFO just landed and posted this here
>> это называется «заблуждение»

заблуждение в чем? сдается мне, вы заблуждаетесь в том, что я заблуждаюсь

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

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

неправда ваша — не тот же самый:

с циклом я решаю задачу в терминах "аккумулятор, цикл, итерация, условие, etc."

а с Haskell я решаю задачу в терминах задания

>> Просто синтаксис позволяет простые случаи "свернуть"

свернуть позволяет не синтаксис, а семантика языка (функции первого класса, карринг, ленивое вычисление), в языках без этих свойств так "свернуть" не получится

и не простые случаи — а любые случаи, т.к. сложные случаи разбиваются на простые
1) поясните что вы имеете в виду под функцией первого класса
2) Карринг - чистой воды синтаксический сахар (http://ru.wikipedia.org/wiki/%D0%9B%D1%8…) -> синтаксис. легко реализуется перегрузкой операторов (например) со своими типами. букв будет больше но поведение - гибче.

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

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

Не говоря уж о том что фильтрация данных в промышленных маштабах делается на стороне SQL сервера а никак не в коде. Да собственно подобные нотации чем-то SQL и напоминают :)

А вообще тут уже на вкус и цвет имхо. спор о терминах. Посему записывание последовательности действий интерпретатору через точку, >>> и т.п. продолжу считать синтаксическим сахаром, уж простите...

Т.е. мне на самом деле неважно что интерпретатор может это ускорить поменяв порядок и т.п. Потому что если программист не понимает хотябы в общих чертах как (технически, т.е. да, через циклы!) выполняется кусок программы то его к серъезной системе просто нельзя подпускать! Потому что либо он наворотит такого что потом полгода всему отделу разгребать либо всеже разберется как оно работает... а когда разберется весь этот сахар по большому счету уже не нужен. и язык не важен. Что c# что хаскель используют одну и туже человеческую логику, а число букв не имеет значения. со своей собственной практики.
Имхо
>> Карринг - чистой воды синтаксический сахар

синтаксический сахар over what?

как правило, сленговый термин "syntax sugar" используется для обозначения тривиальных преобразований на уровне синтаксиса языка

карринг же в функциональном языке — это неотъемлемое (intrinsic) свойство самой семантики языка, а не преобразование на синтаксическом уровне

>> легко реализуется перегрузкой операторов (например) со своими типами

угу, реализуйте карринг перегрузкой операторов :) это невозможно технически

>> поясните что вы имеете в виду под функцией первого класса

я имел ввиду функции, как объекты первого класса — это когда в языке функция может прозрачно использоваться в качестве значения

к примеру, в сочетании с каррингом я могу создать новую функцию:

List.intersperse "\n"

и сразу же использовать её в контексте другой функции ">>>"

List.intersperse "\n" >>> concat

все это выражение имеет тип "функция от списка" и я могу применить к нему список:

(List.intersperse "\n" >>> concat) ["здесь", "был", "вася"]


>>ленивые вычисления .. не так часто это и нужно на практике.

тут как бы дело не в том, часто или редко это нужно на практике — без этого невозможно написать некоторые программы так, чтобы они завершались

— проверяет число на простоту
isPrime n = ...

— множество всех простых чисел
primeNumbers = filter isPrime [1..]

— три первых простых числа
take 3 primeNumbers


вот эта конструкция [1..] приведет к зависанию в строгом языке

ленивость в общем случае дает возможность писать обобщенно — а ограничения (вроде take 3 из примера) устанавливать выше и не протаскивать их сквозь всю программу — это невероятно полезно в реальных программах

>> плюс все равно, это эмулируется

а вы уверены, что не пропустили первый пример на C# из статьи? там автор как раз эмулировал функциональный код — что получилось? правильно, страшилище

я уже не говорю про, что это жутко неэффективно (в императивной среде компилятор вам такой код не оптимизирует)

>>.. и давления солнечных лучей на мозг заказчика (мы же не для себя код пишем?)

так интересно-то вот что — именно в функциональном языке и легче адаптировать код под нужды заказчика

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

>> и т.п. продолжу считать синтаксическим сахаром

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

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

иногда кажется, что свои слова лучше не иллюстрировать

по-вашему, мне стоило написать в комментарии 200 строк реального кода на Haskell, где это используется?

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

право, смешно
да, я понимаю, прошу прощения. я тоже утрирую.
честно признаться, в практике хаскеля не встречал. встречал пока только активных проповедников (как в реале так и на РСДН). Возможно у меня все впереди! :)

А вот 200 строк реального кода как-оно-есть было бы и правда очень интересно увидеть. Серьезно. Можно в личку?
UFO just landed and posted this here
код из своих проектов я выкладывать в public domain не собираюсь

но охотно расскажу, как именно ленивость применяется в реальном коде

представьте себе работу с очень большой или вообще бесконечной (ну например граф с циклами) структурой данных

в моей практике типичный паттерн с ними был такой — как-то обработать и отфильтровать (выборка)

в императивном языке обычно делают так — для выборки используется «паттерн» визитор, в визитор передается функция, которая обрабатывает

то есть, получается IoC (inversion of control) — а это жуня, т.к. приходится выворачивать flow кода наизнанку, а вместе с ним и мозг (когда читаешь такой код)

в Haskell же ленивость позволяет обойтись без IoC в коде (фактически, ленивость — это такой power abstraction над IoC) — что пишешь, то и получаешь, и не паришься о том, что структура данных может быть гигантской или бесконечной

пример, который я привел — именно это и показывает, просто вы не хотите это видеть, вы видите в нём не содержание, а форму (множество простых чисел, бла-бла-бла) :/

>> что все их «достоинства» лежат строго в вашем воображении?

по-моему, они очевидны — такой код хорошо пишется, хорошо читается и хорошо компилируется

разве можно желать бОльшего?

и это не серебряная пуля (никто не называл это так) — просто потому, что это классическая дырявая абстракция (по Джоэлу)!
UFO just landed and posted this here
>>вот на C++ легко можно реализовать .. но это вовсе не является поводом встраивать его в синтаксис языка.

так вообще-то и в Haskell это не является синтаксисом языка — ">>>" там это обычная функция

и в C++ и в C# вы никогда не повторите приведенный код на Haskell — понимаете, в этих языках нет карринга (currying)

>> «практически человеческое» — это замечательный аргумент.

согласен

>> попробуете по такой методологии построить какое-нибудь сложно-составное предложение

зачем? я разобью его на несколько простых предложений

собственно, как и в любом другом языке

>> «укорачивающий» синтаксис
>>вставить в процесс хотя бы один if .. то «укорачивание» обернется против вас.


а это не синтаксис и он ничего не укорачивает — в Haskell нет другого способа писать код

да, там можно сделать цикл — но это сложнее чем сделать map, поскольку Haskell основан на лямбда-исчислении, а не на модели Тьюринга

советую вам всё же написать пару строк кода на Haskell или ML прежде чем комментировать код на этих языках
>> разница только в восприятии кода вами (человеков), не более того

а это неправда

разница также в восприятии кода машиной

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

с императивной программой у машины такой свободы нет — доступные оптимизации лежат совсем в другой плоскости, на целый уровень ниже

функциональный код фундаментально проще — математически

а вам почему-то кажется, что это какая-то синтаксическая надстройка

проблемы тут есть, конечно — к примеру, сложно предсказать, как именно будет интерпретирован функциональный код в императивной среде исполнения — во многих случаях это неприемлемо (когда требуется максимальная эффективность)

вот только многие люди склонны ставить знак равенства между императивностью и производительностью (например популярно заблуждение "C++ это быстро") — а это не так

в императивной среде куда легче сделать говенный супер-неэффективный код (и делают!!!) — и машина не сможет его оптимизировать

функциональная же среда намного более толерантна - в ней можно сотней способов сказать одно и то же, но в большинстве случаев все эти способы интерпретируются абсолютно одинаково
UFO just landed and posted this here
>> изучая теорию «функционального программирования»

теория ФП (а точнее, теоретическая основа) — это лямбда-исчисление

>> что очень много программировал на «функциональном языке» ECMAScript, он же JavaScript

это из-за того что вы путаете intrinsically functional язык (Haskell, ML-семейство) и императивный язык, позволяющий программировать функционально (коим являются JavaScript, Python и еще много разных)

их интерпретаторы совсем разные, они по-разному видят программу (Haskell - это синтаксический сахар над типизированым лямбда-исчислением, JavaScript - это в разы более сложный — в математическом смысле — язык, и за ним не стоит никакого строгого математического фундамента, это просто ad-hoc каша — неудивительно, что это толком никак не оптимизируется)

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

>> и расскажите поподробнее про заблуждение «С++ — это быстро», я хочу чтобы у меня открылись глаза :)

да чего стоит только забыть поставить "&" и передать аргумент по значению, а не по ссылке

я уже не говорю про чудовищный менеджмент памяти (new/delete), который при наивном использовании STL или любых других RAII-объектов вам зафрагментирует кучу так, что потом и два байта не выделить (в особо запущенных случаях)

только не надо сейчас загибать пальцы и рассказывать про то, что руки должны расти из правильного места — C++ это язык не для людей, а для мутантов с многолетним опытом наступания на грабли в этом самом C++, вроде меня — и, знаете, я этим совсем не горжусь; мне жалко, что я убил несколько лет жизни на ковыряние в говне.

>> к тому же map — это цикл «в один конец», в нем невозможно сделать break, любой if внутри map превращает код в нечитаемый кошмар

map это не цикл, и в нем не требуется делать "break" и "if"

и какой такой нечитаемый кошмар? не будьте голословны — приведите пример, где вы увидели нечитаемый кошмар

вы сейчас пытаетесь проецировать свой опыт программирования в императивных языках — так ничего не выйдет

там программируют по-другому

объяснять здесь, как именно — я не собираюсь, почитайте SICP или какой-нибудь "Yet Another Haskell Tutorial", на худой конец; напишите какую-нибудь несложную софтину на Haskell, и тогда можно будет о чем-то конструктивно говорить, а сейчас наша дискуссия по сути бессмысленный флейм
да, кстати, не надо думать, что я здесь обосрал все низкоуровневые языки

я люблю C — он почти совершенен (семантически), хоть синтаксис там и корявоватый местами

а вот C++ это уродливое говно "ни о чём" — хоть оно может быть очень удобным, если правильно его готовить

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

в терминах Сполски, это на порядки более дырявая абстракция, чем Haskell — слишком легко написать код с непредсказуемым поведением
UFO just landed and posted this here
я вам вполне понятным языком ответил, почему "C++ это не быстро" и как применяется ленивость

поинтересуюсь, кстати: у вас есть опыт разработки софта на C++ или вы про него только слышали?

>> с учетом «код из своих проектов я выкладывать в public domain не собираюсь»

ну, охуенная аргументация вообще: "покажи код — нет — да тебе стыдно!"

детский сад

>> мне в ответ начали гнать

«не хами, парниша»

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

можете и дальше продолжать "плакать, колоться и лезть на кактус", как те ежики из анекдота — адекватные люди меня услышали, с вами же мне говорить не о чем
UFO just landed and posted this here
> вы сейчас пытаетесь проецировать свой опыт программирования в императивных языках — так ничего не выйдет

Эх, каждый раз вспоминаю университетский курс Хаскела, когда мы с товарищем покопались в семействе map и fold и уместили решение в 15 прозрачно читаемых строчек, а другие долго объясняли бедной преподше, как работают их листинги на пару страниц :)
ну, хоть кто-то меня понимает

а вообще я удивлен, что в ВУЗах уже преподают Haskell — прогресс, не иначе
UFO just landed and posted this here
UFO just landed and posted this here
Это принципиально разные языки, то что вы написали — это примерно как корявый перевод оригинала с другого языка. Чем хуже? Тем же, чем перевод хуже оригинала.

Почитайте, чем ленивое (lazy) лямбда-исчисление отличается от машины Тьюринга, вопросы отпадут.
UFO just landed and posted this here
А тут вот явой пугают. А .NET вообще не Ъ. и тд и тп.
По ссылке не читал, но считаю, что .net не самая плохая тихнология, а вот C# да, не айс, F# куда приятнее.
А чем именно C# так не угодил, кстати?
Тем что это императивный язык.
Хм, читая статью сложилось впечатление что у автора при написании кода на С# начинается какая-то паника из-за обилия символов. Ну разные языки - по разному и реализации алгаритмов выглядят. Выше уровень - визуально код красивее. И такие вот "страхи и возмущения" попахивают шизой =))
да, на x86-ассемблере тоже реализации алгоритмов по-другому выглядят

и покажите мне пальцем на того, кто не шизанется написать пару сотен таких вот реализаций на x86

а так да, всего-то лишь — символов больше

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

стресс - это объективный критерий

если я мыслю задачу в терминах списков и свёрток, то транслировать это в циклы и состояния при кодировании на C# - больно

хорошо лишь тем, кто по-другому кроме как в императивных терминах думать не умеет
У Грэхэма есть статья про то, что идея оценки языка по тому, "сколько раз надо по клавишам стукнуть", не так абсурдна, как может показаться.
http://paulgraham.com/power.html
(да, сам автор крэйзи на всю голову, и да, написано по типичному для него шаблону "зачмырить всё, что не лисп, а потом похвалить лисп", но по-сути идеи излагаются здравые)
Однозначно понял только что код на Питоне и Хаскеле кажется мне каким то не логичным и неестесвтенным. Возможно потому что нет опыта...но хм...
Это как например в сях любят писать if ? then : else.
Я конечно понимаю что краткость записи, но краткости вроде как можно добиться и грамотным разнесением кода по процедурам и методам.
Не позиционирую себя как кодер, высказался потому что стало страшно за людей которые будут чейто код доделывать :).
да им и так страшно будет, доделывать чужой код — работа неблагодарная, на чём бы и как бы этот код ни писался

кроме того, в крупных проектах используются mainstream-технологии (а не Haskell) и применяются определенные policy при кодировании, что облегчает задачу
Дело не только в синтаксисе, просто функциональный подход осильно отличается. К примеру когда мне нужно отфильтровать какие-то данные из списка, сделать с ними ещё что-то, потом ещё, на C++ приходится городить большой цикл с кучей когда, и даже если разносить его на функции, вместо цикла использовать for_each то всё равно он грамоздк. На любом функциональном языке это парочка применений map/filter/lambda/reduce и т.д. (в Haskell и Python так вообще можно списковыми включениями, ещё короче) в ОДНУ строку, причём короткую и выразительную, как математическая формула.
Вобщем советую в наш лагерь :)
Не удержался :))) JAVA:

test.remove(""); String result = StringUtils.join(test, "\r\n");

Ничего дополнительного мне писать не нужно, всё уже написано в библиотеках :) А в целом, я всё жду Jython, чтобы наконец объединится с фанатами Python для более плотного совместного творчества. :)
Упс, там через метод :) Ну ладно, ладно Python круче :)
Статья довольно стара. В конце концов на дворе 2008 год и есть C# 3.0
string.Join("\n", myList.Select(item => item.Description()).Where(s => s != "").ToArray());
или
string.Join("\n", myList.ConvertAll(item => item.Description()).FindAll(x => x != "").ToArray());
или при наличии метода расширения и что-нибудь в стиле
myList.Select(item => item.Description()).Where(s => s != "").Join("\n");
Чем не функциональный стиль?
Абсолютно согласен. Имея такие мощные возможности, как Extension methods, Лямбда-выражения и LINQ, С# уже превратился в функциональный язык, не потеряв ни капли от ООП.
Лично мое мнение - Haskell помог мне увидеть новые подходы в программировании, иблагодаря ему я очень легко перешел на C# 3.5.
да, это типа monad comprehension :)

а всё благодаря тому, что Microsoft знает, кого нанимать на ключевые посты

у LINQ ноги растут из Haskell
Все очень верно с этой точки зрения!
Просто вот люди любят устраивать холивары по поводу ООП versus functional-style.
Так, по-моему, они запросто сосуществуют НА РАЗНЫХ УРОВНЯХ!
Объекты используются, допустим, для описания бизнес-логики и способов взаимодействия сущностей на высоком уровне. А на самом низком уровне, на уровне алгоритмов - функциональный стиль! А как еще можно описать алгоритм, кроме как функционально! Или декларативно (но это уже немного другая тема).
Читал в оригинале, там правда автор ещё в конце пишет, что заголовок выбрал для привлечения внимания. Действительно, я на своём примере убедился. На работе приходится разрабатывать на C++, а в свободное время на Python, также изучаю haskell и иногда просто обидно, что в C++ приходится городить кучу кода которая в Python я уверенно делаю одной, коротенькой строкой в функциональном стиле.
Автору оригинальной статьи еще расти и расти над собой. Если изучение перпендикулярных концепций мешает ему в жизни, если он видит минусы в ущерб плюсам у C# и не видит своих собственных минусов Хаскеля, который невозможно использовать также универсально как C#/C++ - то он лишь в начале Пути познания... что все в мире - относительно

Питон вообще не к месту... ставить в одной строчке питон и хаскель - это откровенный бред.
Питон самый обычный линейный скриптовый язык, только со своим синтаксисом и небольшим количество синтаксического сахара (который зачастую трудней читать... ага, из-за того что все в одну строчку пытаются сделать). Запихивание в одну строчку даже простых циклов - это вообще минус. Нет такого кода который не меняется и рано или поздно в цикл потребуется чтолибо добавить после чего так и так цикл придется что? правильно. расписать руками
Дело вкуса, мне например проще читается в одну строчку и быстрее. И добавить туда что-то - никаких проблем. Тут фишка не только в том что "в одну строчку". Фактически в Питоне объявляешь список и сразу в нем пишешь как его заполнять. Или изменил скобки на круглые - и уже это не список а генератор.
Мне кажется, статья сознательно провокационная, поэтому как побочный эффект вызывает такие заявления как "Автору оригинальной статьи еще расти и расти над собой...".
Отличная реклама Питона и Хаскеля :) Соглашусь практически со всем из пункта 1.
Как начинающий программист на python'e говорю всем спасибо за комментарии, ибо они оказались даже интереснее чем сама статья :)
ИМХО каждый язык хорош там, где он нужен. Для каких-то задач лучше использовать С#, для других Haskell, для третьих - Пролог например.
Мы же не обсуждаем что лучше, пистолет ТТ или ПЗРК Стингер.
лучше — это мера весьма контекстно-зависимая

для моей больной головы лучше Haskell, т.к. мне во многих случаях удобнее думать на нём

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

индус за $500/month лучше Haskell'а, да

собственно, статья не про это
В C#.NET 3.5 появились анонимные функции (лямбда, если хотите). Автору рекомендую попробовать, код из статьи неплохо бы уменьшился.
А к функциональному и декларативному коду вместо императивного на C# тоже склонен :) Люди сильно ругаются, пытаясь потом понять такой код.
Ну в шарпе анонимные функции и лямбда-выражения - это разные вещи, хотя одно и использует другое. Впрочем, и то и другое очень применимо и правда существенно уменьшает код.
Просветите о разнице?
Ну здесь не столько разница, сколько одно является "наворотом" поверх другого, то есть лямбда-выражения используют механизмы анонимного делегирования. Также верно то, что не все возможности анонимных delegates доступны в лямбдах. Просто технологии разные все равно, хотя появились одновременно в C# 3.0.
Лямбду, как я понимаю, вообще сделали просто для упрощения синтаксиса для наиболее распространенных ситуаций, где требуется делегирование.
Спасибо за пинок в нужном направлении, теперь, после поиска и прочтения пары статей, всё встало на свои места.
С# 3 я использую в работе

если переписать код из примера на LINQ то он ничем не будет отличаться от декларативных примеров из статьи, разве что синтаксис понятнее тем, кто работал с SQL

к сожалению, помимо C# мне также приходится использовать множество не-гибридных, классически императивных языков (C/C++, PHP, Java), и не думаю, что ближайшие несколько лет что-то изменится
Да, Вы правы, код на LINQ тут бы очень хорошо смотрелся. Было бы кратко, без "нудных циклов", но при этом очень выразительно, что позволило бы легко читать этот код. Опыт показывает, что анонимные функции сторонних людей ввергают в ужас неописуемый.
Совок развращает, когда вылез из песочницы и сел за стол, то обнаружил, что не могу есть вилкой суп, я потратил на этот суп много времени, я обнаружил, что все время думаю над тем, как я бы ел суп совком, сидя в песочнице. Совок отстой. Вилка крутая.
У автора в заметке промелькнули мысли по поводу функционального и ОО-программирования и мышления.
Так вот, я думаю, что от языка это не зависит. Язык действительно зависит от задачи и от предпочтений автора кода. А вот как мыслить - "функционально" или "объектно-ориентированно" - вот в этом вся соль. А как при этом еще стать "лучшим специалистом"?

Ну что тут я могу сказать. Могу посоветовать автору хотя бы поинтересоваться одной темой и, возможно, понять - Test-Driven Development IS a rule!
Это как раз к вопросу о смене "окружения". Надо менять сами принципы и подходы к написанию кода, а не язык. Надо прекращать писать код, который "возможно и не пригодится".
Конечно, против Test-Driven-стиля разработки тоже есть аргументы, но они с лихвой перекрываются достоинствами подхода к программированию и проектированию.


P.S. Кстати, есть один очень красивый язык - Ruby ;)
а насчет ООП - для меня это "процессы, обменивающиеся сообщениями" (вот тут мне ближе всего Erlang)

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

у нас ведь что в учебниках написано : "инкапсуляция, наследование, полиморфизм" — вот все и повторяют эту мантру как заведенные попугайчики
Да нет, не пишется так в разумных учебниках. Это так “читается” у некоторых.

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

А вот “инкапсуляция, наследование, полиморфизм” – это технические возможности ООП ориентированных языков, которые позволяют более удобным образом эту методологию поддержать. В общем случае, вы можете использовать ООП дизайн, делая при этом реализацию на абсолютно любом языке (хоть на ассемблере). Вам просто придётся внутренне придерживаться некоторых соглашений по организации кода и это не будет выглядеть так наглядно как в ООП языках.

Давая определение ООП в упрощённом виде “... процессы, обменивающиеся сообщениями...” вы просто запутываете себя и других. Собственно, как и автор заметки, смешал в кучу код отдельно взятой функции с парадигмой ООП.

Смотреть надо ширше. :-)
вы как-то очень сложно про ООП думаете

смотреть надо проще :)
Смотреть нужно "правильно". Что бы не обзывать самокат паровозом.
Абсолютно согласен.
И при этом для описания собственно алгоритма может использоваться только функциональный или декларативный код. Объекты нужны для описания сущностей на более высоком уровне, на уровне проектирования, и для использования технических особенностей, таких как инкапсуляция, полиморфизм и наследование. А в методах самих классов то - функциональный стиль по сути. Последовательность кода, который должен выполниться для решения задачи и выполнения тестов.

Так что полностью поддерживаю "ООП дизайн + реализация в каком угодно стиле".

P.S. Кстати, есть один очень красивый язык - Ruby ;)

Как правильно что вспомнили :)- допустим вот

list.each{ |t| if t.description!= nil then string << t.description << "\n" end}
Эх, ещё бы компилятор для этого всего иметь, который бы вместо создания кучи временных списков\объектов, сразу бы выделял требуемый объём памяти под строку и соответствующим образом её заполнял. А так.. это игрушки, видимость семантитки.
Почему же игрушки? Часто в императивных языках поступают описанным образом, предвычисляя длину результирующей строки? Да ни разу, конкатенация в цикле, как правило, всех устраивает. И декларативный код по эффективности такому подходу не уступает.
Императивные языки хотя бы дают возможность описать "как" это делать - сознаются в том, что они глупы и незнают "как". Функциональные же говорят: я знаю "как", говори "что"; к сожалению их "как" очень далеко от эффективного "как". Кстати, выше был пример со StringBuilder'ом..
Это всё разговоры в пользу бедных, их можно продолжать до бесконечности: Си и ассемблер, C++ и Си, C# и C++...
На мой взгляд, дело даже не в быстродействии, а в предсказуемости этого быстродействия. Чем выше уровень абстракции, чем больше невидимой работы производит компилятор, тем сложнее человеку оценить сложность записанного в коде алгоритма.
Но никто ведь и не обещал серебряной пули? Программист на декларативном языке не освобождается от обязанности при необходимости разобраться «как» происходит описанное им в коде «что». Точно так же, как программист на C++ должен знать в каких случаях, скажем, происходит копирование объектов, как работают ссылки и т. п., так и программист на Haskell должен быть осведомлён об эффектах чистоты и ленивости. С другой стороны, разве мало народу пишет на скриптовых языках (которые, кстати, могут на некоторых задачах с треском проигрывать компиляторам декларативных языков), нисколько не задумываясь о нижнем слое, полагаясь на «автомагические» вещи? Иногда это приводит к WTF, а иногда просто работает.
Декларативные языки — это инструмент, который при должной квалификации серьёзно повышает отдачу, только и всего.
Увидев фразу «не утилизируя эти фичи», подумал, что это калька с английского варианта, ан нет, в оригинале все вполне по-человечески. В остальном спасибо, перевод качественный.

Автор как-то не по назначению использует Питон, по-моему. ФП — это здорово, но кто мешает писать на нем качественный императивный и объектно-ориентированный код, тем более, что эти возможности в нем представлены куда лучше, чем средства функционального программирования (последние Гвидо очень не любит и все время норовит открутить)?
Да ну, list comprehensions и generator expressions на функциональщину злобную никак не тянут. Сколько знаю питонистов, используют вовсю, и я в их числе. "/n".join(...) — это абсолютно стандартная идиома.
На Гвидо тоже наговаривать не стоит, из 3.0 он убрал только reduce (в простонародье fold), который с громоздким синтаксисом питоновских лямбд действительно использовать несподручно.
+ kawa, ага. Везёт же некоторым.
Не знаю, у меня такой проблемы нет. Когда пишу на C# — пишу на C#. Когда пишу на Python — пишу на Python. И ерундой не занимаюсь.
UFO just landed and posted this here
Аплодирую. Стоя аплодирую! :)

mas.map {|foo| foo.description}.compact.join("\n")
чем-то напоминает древнепрограммисткую забаву времен 640Кб памяти "сэкономь два байта"
мне это напоминает работу скульптора

«Perfection is finally attained not when there is no longer anything to add but when there is no longer anything to take away»

у каждого свои ассоциации
Странно - Вы же что то разумное по теме статьи писали чуть выше - а отличить "сэкономь два байта" от оптимизации алгоритма не хотите.

К тому же - это не обработка примеров кода приведенных в статье - это реализация того же примера на Ruby - в добавление к имеющимся Python/Haskell/С#
ну это была шутка юмора. Злая немного, признаю
стараюсь подобрать язык под задачу.
хорошая статья, но во многом выражает лишь личное отношение автора к языкам. спасибо за пост.
(пишу на python и java)
на С#, вместо примера из статьи можно так:

string retval = "";
foreach (Foo foo in mylist)
retval += (foo.description() + "\n").Trim()

retval = retval.Trim();
однако, сходу понять, что в этом коде происходит — мне не удалось

проблема с чтением императивного кода в том, что приходится в голове интерпретировать его выполнение

такой вот write-only код
UFO just landed and posted this here
у меня немного оффтопный вопрос: как вы сделали, что код с отступами?
при включенном автоформатировании хабрахабр так рендерит параграфы <p>

а еще есть <blockquote>
>>Когда я впадаю в ступор при написании кода на C#, я иду и переписываю этот код заново на Haskell и Python
Хм, он этим на работе занимается? Представляю себе человека, который, впав в в ступор при виде сложного (для него) кода, не обращается к документации и не спрашивает у коллег, а переписывает код на другом языке и в другой парадигме. Видимо его коллеги истинные буддисты, раз он все еще не уволен с этой омерзительной работы, где заставляют (о, ужас!) писать императивный код.

А вообще, и Haskell, и C# поддерживаются Microsoft, и C# потихонечку двигается в сторону всякой функциональщины. Так что следующей больщой вещью от Microsoft видимо, будей некий Func#tional, гибрид от которого будут просто в восторге странные люди вроде автора этой статьи. Ну и, конечно же все те бедолаги-программисты, которые volens-nolens будут вынуждены писать на этом языке "бизнес-приложения"
>> Представляю себе человека, который, впав в в ступор при виде сложного (для него) кода, не обращается к документации и не спрашивает у коллег, а переписывает код на другом языке и в другой парадигме.

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

>> Так что следующей больщой вещью от Microsoft видимо, будей некий Func#tional

не следующей

>> Ну и, конечно же все те бедолаги-программисты, которые volens-nolens будут вынуждены писать на этом языке "бизнес-приложения"

давайте не будем играть в футурологов

вместе с технологиями меняются и сами люди

15 лет назад мы писали на C и в ус не дули, зато вот сейчас бедолаги-программисты ну прям вынуждены писать на C#, где — о, ужас — есть generics, лямбды и LINQ
Безусловно, времена меняются.
Вот 15 лет назад большая часть софта была написана на С/C++ и были функциональные языки, которые были малопопулярны (особенно после смерти лисп-машин), но служили источником идей для мейнстрима. И тогда у программистов были наборы коллекций и трансформаторов, предназначенных для промышленного программирования (правда, зачастую у всех разные). А у функциональщиков еще были лямбды (круто!).
Сейчас все поменялось. Большая часть софта теперь написана на C и C++, функциональные языки теперь малопопулярны, но служат источником идей для мейнстрима. А у программистов теперь есть лямбды, дженерики и LINQ. И еще Билл ушел. Прогресс неумолим
история развивается по спирали — сейчас функциональщину можно встретить даже на хабрахабре :)
Ребята, да какая разница на чем писать... :)
Вы опять подходите из того, что в начале инструмент - потом архитектура программы.
Мне вообще не понятно слышать такое: это гвоно, а это класс. Какой-то детский лепет, а потом все выбегают и начинают меряться пиписьками...
Какая разница на чем написана архитектура и то что будет делать программа.
Прочитав выше складывается такое мнение, в стиле... дайте мне экскаватор я вам дом построю. Для того чтобы построить дом... надо сначала архтектуру его сделать, а для того чтобы сделать архитектуру надо другие совсем знания, а не водительское удостоверение экскаваторщика. В конце концов небольшой домик можно и "лопатой" построить.
Извините что 2 раза написал... какой-то глюк был.
>> Вы опять подходите из того, что в начале инструмент - потом архитектура программы.

для меня — в начале инструмент, а уже потом всё остальное, т.к. я не сторонник RUP и подобных дисциплин "сначала всё-всё проектируем на бумажках, потом рендерим наши мега-blueprint'ы любым подходящим инструментом"

когда работаешь над постоянно меняющимся прототипом — гибкость инструмента неоценима, с плохим инструментом просто пропадает мотивация и желание что-то делать
Так вот с этого и надо было начинать. Дескать так и так, мне пофиг что я пишу, для кого я пишу, зачем я пишу и правильно ли я пишу... Мне нравится сам процесс.

Ну как у Ржевского - детей не люблю, но сам процесс их создания - импонирует. :-)
не все работают в офисе джуниор-программистами и кодят то, что им скажут

кому-то приходится разрабатывать проекты с нуля — здесь эффективность прототипирования имеет решающее значение

>> Дескать так и так, мне пофиг что я пишу, для кого я пишу, зачем я пишу и правильно ли я пишу

вы не дружите с логикой
Угу. Я сразу и не понял, что я работаю в оффисе джуниор программистом. Хотя и оффис вроде как мой. Денех стоил.
Учиться вам и учиться Алекс. Адью. :-)
а я вас и не имел ввиду

пальцы мешают в двери офиса проходить, наверное
Ребята, да какая разница на чем писать... :)
Вы опять подходите из того, что в начале инструмент - потом архитектура программы.
Мне вообще не понятно слышать такое: это говно, а это класс. Какой-то детский лепет, а потом все выбегают и начинают меряться пиписьками...
Какая разница на чем написана архитектура и то что будет делать программа.
Прочитав выше складывается такое мнение, в стиле... дайте мне экскаватор я вам дом построю. Для того чтобы построить дом... надо сначала архитектуру его сделать, а для того чтобы сделать архитектуру надо другие совсем знания, а не водительское удостоверение экскаваторщика. В конце концов небольшой домик можно и "лопатой" построить.
Ламерство.
Хотя может теги ("пуля - дура, цикл - молодец") и намекают на то что статью не следует воспринимать всерьез..
это сатирическая статья, FYI
Очень заинтересовала статья. Прям не вериться, что функциональный язык может на сколько упростить жизнь. Раньше читал чуть-чуть про хаскел и тому подобные языки, но все время никак не мог представить как именно он подойдет к моей работе. В основном все примеры сводятся либо к математическим функциям (которые за меня выполняет БД), либо к формированию строк (тут не поспоришь, любой программист часто использует такие циклы), но моя работа не состоит в основном из формировании строк (такие простые циклы используются один на 1000 строк кода), поэтому их оптимизация на сколько я понимаю будет только для души. При этом существуют другие более сложные и запутанные места, вот, например, реализация сериализации объектов в файловый поток

void WriteParamItemToBlob(ParamItem item, /*out*/ CBlob *resultBlob)
{
resultBlob->WriteInt(1); // Версия
resultBlob->WriteString(item.name);


resultBlob->WriteChar(item.isList);

if (item.isList) {
if (item.list) {
resultBlob->WriteChar(1); // Имеются сведения о списке

// Используется косвенная рекурсия
WriteParamsListToBlob(item.list, resultBlob);

} else {
resultBlob->WriteChar(0); // Нет сведений
}
} else {
if (item.value) {
resultBlob->WriteChar(1); // Имеются сведения о значении
item.value.SaveToBlob(resultBlob);
} else {
resultBlob->WriteChar(0); // Нет сведений о значении
}
}
}



void WriteParamsListToBlob(ParamsListBase list, /*out*/ CBlob *resultBlob)
{
resultBlob->WriteInt(2); // Версия
resultBlob->WriteString("ParamsList");
resultBlob->WriteInt(list.Count()); // Количество

ParamItem item = list.GetFirst();

while (item) {
resultBlob->WriteChar(1); // Отмечаем, что есть ещё записи.
WriteParamItemToBlob(item, resultBlob);

item = list.GetNext();
}

resultBlob->WriteChar(0); // Отмечаем, что больше записей нет.
}


Задача такая: существует коллекция элементов, которая может содержать элементы и такие же коллекции (рекурсивная структура, на сколько я знаю для ФЯ это наиболее удобная форма хранения данных). Требуется сериализовать коллекцию в файловых поток (resultBlob это stream, который потом записывается в файл). Возможно ли такие не очень простые функции преобразовать в более понятный вид. Особенно хотелось обратить внимание на формат потока, так как взаимодействие осуществляется с другой частью системы, которую пишут другие люди, поэтому протоколы взаимодействия четко описанны и так же четко должны поддерживаться.
После продолжительного отпуска(>3 месяцев) теперь не могу толком писать код на Java.

Для меня это стало настоящим императивным кошмаром. Хочется бросить всё и уйти из программирования. Самое страшное в этой ситуации то, что мне не с кем поделиться своим «горем» — кругом одни «фанаты» императива и ООП.
Sign up to leave a comment.

Articles

Change theme settings