LINUX.ORG.RU

Функциональная парадигма

 , ,


2

7

Что-то в последнее время начали хайпить функциональное программирование. Мол, стиль со взглядом в будущее, распараллеливание, оптимизация, замена устаревшему ООП, который не способен идти в ногу с современными процессорами. Есть ли здесь люди, которые пишут на Haskell или тому подобных языках? Есть ли профит переходить на ФП? Или мультипарадигмость С++ и Java исправят ситуацию?


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

Брайт, и Александреску ни разу не теоретики

О том, что Брайт практик и спору нет. А вот то, что Александреску теоретик, так это же очевидно. Он даже в Facebook-е работал на должности исследователя.

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

Чисто по фану, что было бы, если бы из с++ сделали хаскель :D

auto avg(auto xs){
    auto (s1, n1) = foldl([](pair(auto s, auto n), auto x){
                                 return pair(s+x, n+1);}), 
                          pair(0, 0));
    return s1/n1;
}

Что-то синтаксис хаскеля мне нравится больше =)

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

В C++14 это выглядит, например, так:

using namespace std;

template<typename C>
auto avg(const C & xs) {
  using T = decltype(*begin(xs));
  auto s = accumulate(begin(xs), end(xs), make_pair(T{}, 0u),
    [](auto p, auto x) {
      return make_pair(p.first+x, p.second+1u);
    });
  return s.first/s.second;
}

Но я бы не сказал, что это идиоматический код для C++.

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

А вот то, что Александреску теоретик, так это же очевидно.

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

Он даже в Facebook-е работал на должности исследователя.

Исследователя чего?

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

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

По-твоему, если человек «с областью разработки языков программирования» не знаком, но берется, то он «практик». Ну Окай.

Исследователя чего?

Официально он там назывался research engineer. Что именно исследовал — хз. Судя по том, что при нем на D написали lint для C++, а один из докладов, который он делал, касался какой-то специфической оптимизации shared_ptr, то исследовал какую-то фигню :)

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

По-твоему, если человек «с областью разработки языков программирования» не знаком, но берется, то он «практик»

По-моему, если человек не знает теории того дела, за которое берется, то он не теоретик. Но, поскольку он им занимается, он практик.

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

Я заметил пренебрежение и презрение к теоретическим познаниям.

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

Продолжаем страдать фигней.

Хаскель код курильщика :D Теперь с циклами!

avg xs = runST $ do
    s <- newSTRef 0
    n <- newSTRef 0
    forM_ xs $ \x -> do
        modifySTRef' n (+1)
        modifySTRef' s (+x)
    liftM2 (/) (readSTRef s) (readSTRef n)
Waterlaz ★★★★★
()
Ответ на: комментарий от Waterlaz

Не совсем понял, к чему тот циклы в Хаскеле. Показанный мной C++ код не является, имхо, идиоматический потому, что C++ затачивается на производительность, а подсчет элементов при суммировании нужен только для тех случаев, когда нельзя одной операцией определить длину последовательности. Например, если xs представляет из себя list или set. Поэтому в C++ имело бы смысл разделить реализацию avg для двух случаев: a) когда у нас просто input_iterator-ы и нужно считать количество элементов, и b) когда у нас random_access_iterator и количество элементов можно вычислить простой разностью (end-begin).

using namespace std;

template<typename C>
auto avg_impl(const C & xs, std::input_iterator_tag) {
	using T = decltype(*begin(xs));
	auto s = accumulate(begin(xs), end(xs), make_pair(T{}, 0u),
		[](auto p, auto x) {
			return make_pair(p.first+x, p.second+1u);
		});
	return s.first/s.second;
}

template<typename C>
auto avg_impl(const C & xs, std::random_access_iterator_tag) {
	using T = decltype(*begin(xs));
	return accumulate(begin(xs), end(xs), T{}) / distance(begin(xs), end(xs));
}

template<typename C>
auto avg(const C & xs) {
	return avg_impl(xs,
			typename iterator_traits<decltype(begin(xs))>::iterator_category{});
}

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

Названия каких функций в хаскеле тебе кажутся невнятными?

forM_ xs

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

i36_zubov
()

Что-то в последнее время начали хайпить функциональное программирование. Мол, стиль со взглядом в будущее, распараллеливание, оптимизация, замена устаревшему ООП, который не способен идти в ногу с современными процессорами

Это не в последнее время. Это годов с 70-х :) Только тогда у них был маркетинг вокруг искусственных интеллигентов. Пены будет много, результат как обычно.

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

У тебя ошибка, из-за неявного приведения.

Что за ошибка?

Cделай счётчик знаковым в первом avg_impl.

Зачем?

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

есть javascript который тоже вполне си-подобный

автор этого тезиса конечно написал много глупостей, но эту захотелось выделить отдельно. Люблю ЛОР за феерический бред отдельных персонажей в том числе :)

ЗЫ и не надо объяснять что «я имел в виду синтаксис, а там везде все как в сишке с фигурными скобочками и точкозапятыми»

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

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

У тебя шизофазия?

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

Не совсем понял, к чему тот циклы в Хаскеле. Показанный мной C++ код не является, имхо, идиоматический потому, что C++ затачивается на производительность, а подсчет элементов при суммировании нужен только для тех случаев, когда нельзя одной операцией определить длину последовательности.

Ну так и я привел не идеоматический код на хаскеле.

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

В каком из случаев ваш код не идиоматический для Хаскела? Вы ведь несколько примеров кода показывали.

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

Это в каком компиляторе так?

В любом, man неявное приведение типов.

http://ideone.com/eRRt0c

Я говорю про первый impl, а ты показываешь второй. Distance возвращает ptrdiff_t, а он знаковый и с ним проблем нет.

https://ideone.com/WC39N1

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

Ok. Теперь понял о чем речь. Действительно, мой косяк.

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

Ну про то и речь, что если в задаче нужен C++, нужно различать случаи, где n нужно высчитывать во время итерации, а где можно сразу получить n как разность между end и begin.

Поэтому такой лаконичной записи в C++ все равно не будет. Да и, соглашусь, с i36_zubov, нахер она не нужна.

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

Ну про то и речь, что если в задаче нужен C++, нужно различать случаи, где n нужно высчитывать во время итерации, а где можно сразу получить n как разность между end и begin

Ну так и в хаскеле код станет проще, если можно получить n как разность условных end и begin

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

Ну так и в хаскеле код станет проще, если можно получить n как разность условных end и begin

Ну покажите код avg на Хаскеле, в котором будет определяться, можно ли n вычислить как разность, или нет. И в зависимости от этого выбирается тот или иной механизм вычисления среднего.

Кроме того, в своем коде на Хаскеле вы задаете жестко 0 в качестве начального значения аккумулятора. В коде на C++ выбирается начальное значение для типа элемента последовательности. В общем-то это не обязательно должен быть 0.

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

на самом деле к хацкелю есть еще одна претензия - он походу не умеет оптимизировать.

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

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

второе: ежу понятно, что сложения даже несколько дешевле заливки гигабайта памяти. то есть компилятор должен был по идее увидеть, что функция «дешевая» если считать в лоб, вызывает сама себя и скрутить её в цикл. но как оказалось он такое делает только с foldl', -O2 и еще каким-то трахом.

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

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

вспомни себя в пубертатном периоде и не суди слишком строго

ЗЫ впрочем, если ему больше 20и, то его надо не осуждать, а жалеть

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

Лично мне странно слышать претензии по поводу производительности по отношению к языкам высокого уровня. C++ довольно низкоуровневый язык, от него производительность требуется по определению. Haskell весьма высокоуровневый язык. От Haskell-я в первую очередь требуется, чтобы сроки реализации задачи на нем резко сокращались (по сравнению с тем же C++). А уж то, что результирующий код не будет так быстр, как код на C++, ну так это плата за сокращение сроков и трудоемкости разработки.

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

знаешь что я скажу про хацкель.

это эталонный пример как не надо делать.

то, что язык форсят одни гики это показатель. еще больший показатель это их статьи типа «почему цацкель делает вас более плохим программистом». когда адепты на полном умняке рассказывают как нечитабельное говно breathtakingly круче читабельного кода на c#... на решетках игори пишут-с. на говне пишут только потребители говна.

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

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

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

ЗЫ выкати код на с++, тогда и поговорим.

groupBy ((==) `on` length) . filter ("a" `isPrefixOf`) . map (map toLower)
Waterlaz ★★★★★
()
Ответ на: комментарий от i36_zubov

и побольше однострочников. еще бы без пробелов и вообще лихо будет

Тут все идеально читается.

Где код на c++?

Waterlaz ★★★★★
()
Последнее исправление: Waterlaz (всего исправлений: 1)
Ответ на: комментарий от i36_zubov

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

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

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

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

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

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

Вложенные лямбды выглядят проще чем вложенные лупы

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

Можешь проблему жабнутых написать так, как если бы ты писал не на двач?

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

Чистые функции с мутными определениями...

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

Названия каких функций в хаскеле тебе кажутся невнятными? :D

В хаскеле есть практика давать однобуквенные названия (a, b, c, x, y, m, n, k...), а потом, когда буквы заканчиваются, то туда добавят, например, кавычку (a', b', c'...). Ф-и не делают однобуквенными (обычно, хотя и такое бывает), но при этом все равно любят экономить на буквах и дают совершенно невнятные имена. Даже твой пример однострочник демонстрирует этот рак. Нестрогий fold называется fold, строгий fold - это fold', вместо strictFold. Да даже типовым параметрам дают однобуквенные имена, пример типов для линз каноничен. Ни в каком нормальном языке такой рак не пройдет код ревью. В хаскеле - это норма, распространенная даже на стандартную библиотеку. Именно это и есть главная проблема хаскеля - низкий уровень программистов на хаскеле, настолько низкий, что полнейший говнокод в комьюнити считается нормой. Обфускация при помощи поинт-фри стиля, однобуквенные, невнятные имена, использование генерик-кода в тех случаях, когда можно обойтись конкретизациями, игнорирование явных определений типов, неумение использовать систему типов для написания надежного кода, ужасное понимание используемых абстракций - и язык совсем не помогает всех этих факторов избегать. Наоборот.

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

Что-то синтаксис хаскеля мне нравится больше =)

У тебя fold ф-я, а не метод. При чем тут синтаксис? Разница семантическая.

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

Что делает ф-я forM_, чем она отличается от forM, и как это понять из «понятного как и все в хаскеле» имени ф-и? И каким образом понять, что в данном случае надо modifySTRef' (строгую) не зная заранее, как рассахаривается ду-нотация и какая реализация у рассматриваемой монады (и не сделав этого в уме, конечно же)?

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

хацкель нечитабелен.

Без подготовки ни один язык не будет читабелен. Хаскелл пилится не столько для того, чтобы на нём писать боевой софт (хотя некоторые используют), а для экспериментов. Микрософт вкладывает в его развитие, оценивает наработки, и реализует проверенное в своём боевом F# (и C#). Иначе зачем в Хаскелл вкладывать как если не в тестовый полигон.

стараются ... закосов под обфускацию кода.

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

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

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

Что делает ф-я forM_, чем она отличается от forM, и как это понять из «понятного как и все в хаскеле» имени ф-и?

Все достаточно логично. Достаточно один раз глянуть на определения из Control.Monad и больше не будет никаких проблем.

someFunctionM_ :: Monad m => a -> ... -> m ()

someFunctionM :: Monad m => a -> ... -> m b

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

Да не нужо знать, как рассахаривается ду нотация и в уме ничего делать не надо. Простая рекомендация: арифметические вычисления выполнять строго.

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

Нестрогий fold называется fold, строгий fold - это fold', вместо strictFold.

Ну один раз увидеть, что штрихом обозначают строгие функции и все. Какие проблемы?

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

У тебя fold ф-я, а не метод. При чем тут синтаксис? Разница семантическая.

В данном контексте вообще не принципиальная разница.

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

Без подготовки ни один язык не будет читабелен.

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

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

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

Это же идеоматический код. На хаскеле не надо писать идеоматический код?

Все достаточно логично

Достаточно логично что?

Достаточно один раз глянуть на определения из Control.Monad и больше не будет никаких проблем.

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

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

В-третьих, объясни все же, своими словами, пожалуйста - что означает «_» в конце ф-и, где тут логика (почему _ а не '? потому что ' занят? а чего не ^? или %? почему суффикс, а не префикс? почему он nonalphanumeric?), и что, кроме полной профнепригодности человека, писавшего код, мешало дать ф-и человеческий нейминг?

Да не нужо знать, как рассахаривается ду нотация и в уме ничего делать не надо. Простая рекомендация: арифметические вычисления выполнять строго.

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

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

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

Ну один раз увидеть, что штрихом обозначают строгие функции и все. Какие проблемы?

А дать функции нормальное имя один раз и навсегда, в чем проблема? Ах, да, ведь синтаксис хаскеля - дерьмо и становится абсолютно нечитаем с длинными именами!

По-этому все вынуждены рожать code smell с кавычками, подчеркиваниями и однобуквенными неймингами.

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