BZ>>я часто сталкиваюсь с двумя точками зрения — первая "я знаком с ФП, но оно никакой выгоды в программировании не даёт", и вторая "я знаком с ФП, но так и не научился использовать его для повышения эффективности программирования". собственно, это одно и то же, разница только в том, на кого (ФП или самого человека) возлагается вина за отсутствие результата
S>Еще одно мнение в копилку — ФП дает выигрыш на узком классе задач, связанных со сложной работой с динамическими структурами данных (списками, деревьями, etc) — на что оно, собственно, и заточено.
Прошу прощения, но ФП ни под что конкретно не заточено.
Это всё в глазах наблюдателя.
S>А на том, что типично пишут программисты, оно особенно не нужно.
Какие программисты-то?
Yours truly, Serguey Zefirov (thesz NA mail TOCHKA ru)
Здравствуйте, subdmitry, Вы писали:
S>Здравствуйте, deniok, Вы писали:
D>>Это не задача. Это выглядящие бессмысленными упражнения с записыванием значений в непонятные участки памяти, очевидно, доступные глобально.
S>Я считаю, что начинать надо с малого. Лично мне не очень понятно, как добиться на Хаскелле решения такой простой проблемы и (серьезно!) хочу его увидеть.
Что за проблема-то?
S>Оно не такое уж и бессмысленное. У меня при программировании часто возникает код, подобный написанному. Хочу понять, как получить его аналог в функциональных языках.
Лови:
doIt = do
increment vA
vB ! vA --> vD *= 10
vF vG --> vH $= 0
Монады и операторы — твои друзья.
S>Некоторые тут, кстати, заявляют, что Хаскель лучший императивный язык...
Это не тут.
Это в Майкрософте.
Yours truly, Serguey Zefirov (thesz NA mail TOCHKA ru)
Y>>Пойми я тоже не хочу никого унизить, просто тут уже сразу видно невооруженным взглядом, отсутствие какой-либо базы, а без базы, тебе никто не сможет даже объяснить, почему ты не прав.
S>...решение этой задачи на Хаскелле. Особенно интересно в многопоточном варианте.
Приведенноё мной решение будет работать и с несколькими потоками тоже.
S>Если, конечно, наличествующая у вас база это позволяет сделать, а не просто утверждать, что "глобальные переменные это плохо".
sendval ixlist inp v = do
modindex <- nodemodindex node $ take 2 ixlist
asend (oIndexes group fullixlist++oNode node) modindex arity (inp,v)
where
ixlen = length ixlist
fullixlist
| ixlen == 3 =
sum ixlist:ixlist
-- sum (take 2 ixlist):ixlist
-- 0:ixlist
| otherwise = ixlist
node = inpnode inp
group = nodegroup node
arity = inparity inp
nodeS dimn x y ix@[_,i,j,k] = do
r <- fadd x y
c <- ilt k dimn
aif c
(do
k1 <- iadd k 1
sendval [i,j,k1] SInputX r
)
(sendval [i,j] CInputX r)
Сделай-ка аналогичный "ассемблер" на твоём любимом ЯП. Чтобы не менее удобно было — чтобы можно было определять свои "подпрограммы" и тп.
Yours truly, Serguey Zefirov (thesz NA mail TOCHKA ru)
Здравствуйте, VoidEx, Вы писали:
VE>Вот вам полный прикол:
Большое спасибо, это очень интересно.
То есть созданные в одной функции монадические переменные можно передавать в другие функции, но не делать глобальными. То есть для честного решения того примера в функцию DoIt() надо передать 7 переменных, чего народ ужаснулся. А так же передавать их во всю цепочку функций, из которых DoIt() вызывается. Меня сейчас будут пинать, но, признаться, в ряде случаев вариант с глобальными переменными мне нравится больше.
А можно описывать все функции в модуле как where-блок к блоку do в функции main, это не создат ли эффекта, что порожденные в блоке do переменные станут типа глобальными для этих функций?
VE>
VE>main = do
VE> chan <- newChan :: IO ByteReads
VE> s <- getChanContents chan
Насчет последней строчки. Она не лишняя? Или это очистка очереди от какого-то мусора?
VE>
VE>Кстати, я думал, что в Chan может быть один писатель, но не падает. Везёт, или писателей таки может быть куча?
Да вроде оно Control.Concurrent.Chan. По идее должно работать с несколькими потоками.
And if you listen very hard the alg will come to you at last.
Здравствуйте, NotGonnaGetUs, Вы писали:
NGG>з.ы. NGG>К дискуссии о "промышленном" решении можно будет вернуться, когда ФП окажется в массах и массы, пробежавшись по всем граблям n-раз, обобщат их до шаблонов, "запахов" и приниципов
Здравствуйте, NotGonnaGetUs, Вы писали:
NGG>Посмотрел на нашу битву реализаций и решил-таки (благо новый год и есть свободное время) познакомиться с одним из языков формальных спецификаций (Z) поближе, что в итоге позволило взглянуть на поднятую тему под немного другим углом.
NGG>Прежде всего, предложенное обобщение слишком "обобщенное": для того, чтобы перейти к дизайну, а затем реализации, требуется принять ряд решений (наложить ограничения) от которых итоговое решение довольно сильно зависит. Эти ограничения не имеют никакой связи с языком программирования или "стилем" проектирования принятым в этом языке.
Я тоже смотрю на эту битву и недоумеваю, зачем вообще нужны такого рода обобщения.
Может дело в ява культуре, от которой я слишком далек, и подозреваю что из-за
относительной (даже к C++ и С#) бедности языка там без этого просто никуда.
Просто по моему опыту (C++) даже на довольно крупных проектах (сотни тысяч строк и
человеко-годы) такого рода обобщения практически бесполезны, когда нужна правка оказывается
что обобщенно не в ту сторону или проще заново написать пусть даже заплатку чем разбиратся
в слишком усложненом коде.
Ну и еще к разности культур, меня интересуют сейчас функциональные (а до этого динамические)
языки как инструмент для повышения производительности одиночки или небольшой группы.
Для этих целей такие языки очень хороши и по моему позволяют довольно сильно уменьшить
самую рутиную часть программирование — кодирование, так как по сути написание текста
на выразительных языках ближе к проектированию (или к конструированию)
чем к кодированию.
Здравствуйте, thesz, Вы писали:
S>>Еще одно мнение в копилку — ФП дает выигрыш на узком классе задач, связанных со сложной работой с динамическими структурами данных (списками, деревьями, etc) — на что оно, собственно, и заточено. T>Прошу прощения, но ФП ни под что конкретно не заточено. T>Это всё в глазах наблюдателя.
Я под ФП понимаю направление человеческой мысли, разработавшей вполне конкретные языки (Lisp, ML, Haskell, Erlang, etc) со вполне конкретными фичами. Чисто функциями без side-эффектов можно писать и на С++, но его к ФП не причисляют, так как там этих фич и соответствующего синтаксического сахара нет (автоматическое управление паматью, patter matching, lambda functions, curring, high-order functions, etc). Реальная заточка этих фич — работа с рекурентными типами данных.
Естественно, в других языках есть и другие заточки, например, на работу с массивами.
Правда да, есть еще APL-J-K... Но это уже несколько другая область человеческой мысли, уж относят ли ее к ФП или нет.
S>>А на том, что типично пишут программисты, оно особенно не нужно.
T>Какие программисты-то?
Да самые разные. Вот, например, по-видимому самый широкий класс приложений — написание GUI к базам данных. Что-то не слышал, чтобы их вообще кто-то пытался писать на ФЯ. А почему? А потому что разработанные в ФЯ фичи для таких приложений малополезны.
And if you listen very hard the alg will come to you at last.
T>doIt = do
T> increment vA
T> vB ! vA --> vD *= 10
T> vF vG --> vH $= 0
T>
T>Монады и операторы — твои друзья.
Еще нет, все никак не разберусь толком с монадами. Нельзя ли в паре слов описать, как эти vA, vB и т.д. попадают в функцию? Для простоты можно ограничиться только первой операцией.
And if you listen very hard the alg will come to you at last.
Здравствуйте, thesz, Вы писали:
T>Сделай-ка аналогичный "ассемблер" на твоём любимом ЯП. Чтобы не менее удобно было — чтобы можно было определять свои "подпрограммы" и тп.
Могу предложить только интерпретатор Пролога, реализованный на Турбо Ассемблере, и то только в виде бинарника (сорцы утеряны). Смотреть в IDA. http://eoda.by.ru/Data/CrackMes/aliencpu.rar
And if you listen very hard the alg will come to you at last.
S>То есть для честного решения того примера в функцию DoIt() надо передать 7 переменных, чего народ ужаснулся. А так же передавать их во всю цепочку функций, из которых DoIt() вызывается. Меня сейчас будут пинать, но, признаться, в ряде случаев вариант с глобальными переменными мне нравится больше.
Если делать такие функции, то лучше императивный подход.
Прочтите ещё раз изначальную задачу, Вы решили (точнее предложили решение) её и так с кучей глобальных переменных, я их убрал. Возникает мысля, что если писать в ФП стиле, Вам просто не понадобится передавать по 7 переменных, не так ли?
Кстати, хочу посмотреть на это же на Вашем любимом языке, а то будет нечестно
Желательно императивным подходом (т.е. не мой код переписать на любой другой язык, а сделать так, как в этом языке обычно принято).
VE>>
VE>>main = do
VE>> chan <- newChan :: IO ByteReads
VE>> s <- getChanContents chan
S>Насчет последней строчки. Она не лишняя? Или это очистка очереди от какого-то мусора?
VE>>
Этой строкой я беру ленивый список всех попадающих в канал значений, который затем передаю в reader. Так же можно делать с файлами, например. reader, как можно заметить, понятия не имеет ни о каких Chan'ах, что даёт нам ещё одну степень абстракции. Я мог и reader'а-то не писать, а сразу написать, что мне со списком делать.
Здравствуйте, VoidEx, Вы писали:
VE>Кстати, я думал, что в Chan может быть один писатель, но не падает. Везёт, или писателей таки может быть куча?
В канал может писать кто угодно, в чей он области видимости, главное что бы тип записываемых данных подошёл. Фактически это же просто очередь с атомарным доступом (как у MVar)...
Здравствуйте, subdmitry, Вы писали:
S>Здравствуйте, deniok, Вы писали:
D>>Это не задача. Это выглядящие бессмысленными упражнения с записыванием значений в непонятные участки памяти, очевидно, доступные глобально.
S>Я считаю, что начинать надо с малого. Лично мне не очень понятно, как добиться на Хаскелле решения такой простой проблемы и (серьезно!) хочу его увидеть.
S>Оно не такое уж и бессмысленное. У меня при программировании часто возникает код, подобный написанному. Хочу понять, как получить его аналог в функциональных языках.
А нельзя ли поподробнее? С описанием типов всех этих A, B, C, D...
S>Некоторые тут, кстати, заявляют, что Хаскель лучший императивный язык...
Уточнение: не лучший, а самый прекрасный в мире (Haskell is the world's finest imperative language)...
T>>vA = ...что-то там такое...
T>>increment var = do { x <- getV var; setV var (x+1) }
T>>doIt = do
T>> increment vA
T>> vB ! vA --> vD *= 10
T>> vF vG --> vH $= 0
T>>
T>>Монады и операторы — твои друзья. S>Еще нет, все никак не разберусь толком с монадами. Нельзя ли в паре слов описать, как эти vA, vB и т.д. попадают в функцию? Для простоты можно ограничиться только первой операцией.
vA — это название твоей A. В Хаскеле с большой буквы называются конструкторы данных.
То, что increment пришлось определять в отличии от встроенного ++, не беда совершенно.
Yours truly, Serguey Zefirov (thesz NA mail TOCHKA ru)
Здравствуйте, geniepro, Вы писали:
G>В канал может писать кто угодно, в чей он области видимости, главное что бы тип записываемых данных подошёл. Фактически это же просто очередь с атомарным доступом (как у MVar)...
Спасибо, просто у меня почему-то было ощущение, что это один писатель, много читателей. Не знаю, откуда взялось [ощущение].
S>>>Еще одно мнение в копилку — ФП дает выигрыш на узком классе задач, связанных со сложной работой с динамическими структурами данных (списками, деревьями, etc) — на что оно, собственно, и заточено. T>>Прошу прощения, но ФП ни под что конкретно не заточено. T>>Это всё в глазах наблюдателя.
S>Я под ФП понимаю направление человеческой мысли, разработавшей вполне конкретные языки (Lisp, ML, Haskell, Erlang, etc) со вполне конкретными фичами.
Теперь тебе осталось выяснить, как же понимает ФП весь остальной мир.
S>Чисто функциями без side-эффектов можно писать и на С++, но его к ФП не причисляют, так как там этих фич и соответствующего синтаксического сахара нет (автоматическое управление паматью, patter matching, lambda functions, curring, high-order functions, etc).
Вот в лиспе нет pattern matching и currying. Там даже tail call optimization нет. Он всё ещё ФЯ?
(с моей точки зрения, кстати, не так, чтобы особо
S> Реальная заточка этих фич — работа с рекурентными типами данных.
По-моему, здесь мы имеем дело с так называемым non-sequitur.
С логическим скачком, иными словами.
Не видно, как из перечисленных тобой свойств ФП следует заточенность под работу с рекурсивными типами данных.
S>Естественно, в других языках есть и другие заточки, например, на работу с массивами.
А в ФП нет? Почему? "Single Assignment C" does ring any bell?
S>>>А на том, что типично пишут программисты, оно особенно не нужно.
T>>Какие программисты-то?
S>Да самые разные. Вот, например, по-видимому самый широкий класс приложений — написание GUI к базам данных. Что-то не слышал, чтобы их вообще кто-то пытался писать на ФЯ.
По-моему, ты не слышал, как кто-либо вообще хоть что-нибудь писал на ФЯ.
S>А почему? А потому что разработанные в ФЯ фичи для таких приложений малополезны.
А с моей точки зрения потому, что уровень писателей таких приложений в своей массе весьма низок. Потому, что платят мало, потому, что средний наниматель таких программистов сам невысокого уровня.
Yours truly, Serguey Zefirov (thesz NA mail TOCHKA ru)
T>>Сделай-ка аналогичный "ассемблер" на твоём любимом ЯП. Чтобы не менее удобно было — чтобы можно было определять свои "подпрограммы" и тп. S>Могу предложить только интерпретатор Пролога, реализованный на Турбо Ассемблере, и то только в виде бинарника (сорцы утеряны). Смотреть в IDA. S>http://eoda.by.ru/Data/CrackMes/aliencpu.rar
Не уворачивайся. Давай исходник "ассемблера" на твоем ИЯП.
Потрудись немного, уважь старика Зефирова, всё равно сейчас делать нечего.
Yours truly, Serguey Zefirov (thesz NA mail TOCHKA ru)
Здравствуйте, VoidEx, Вы писали:
VE>Здравствуйте, geniepro, Вы писали:
G>>В канал может писать кто угодно, в чей он области видимости, главное что бы тип записываемых данных подошёл. Фактически это же просто очередь с атомарным доступом (как у MVar)...
VE>Спасибо, просто у меня почему-то было ощущение, что это один писатель, много читателей. Не знаю, откуда взялось [ощущение].
Здравствуйте, thesz, Вы писали:
T>Вот в лиспе нет pattern matching и currying. Там даже tail call optimization нет. Он всё ещё ФЯ?
Ну вапще-то используя библиотеки, можно в лисп добавить и паттерн-матчинг, и карринг. А хвостовая рекурсия прямо указана в стандарте схемы, да и в CL тоже есть...
....
T>Потрудись немного, уважь старика Зефирова, всё равно сейчас делать нечего.
эх, а я вот и не заметил эти новогодние дни, потому как отдыхал всего пару дней...
T>>Вот в лиспе нет pattern matching и currying. Там даже tail call optimization нет. Он всё ещё ФЯ? G>Ну вапще-то используя библиотеки, можно в лисп добавить и паттерн-матчинг, и карринг. А хвостовая рекурсия прямо указана в стандарте схемы, да и в CL тоже есть...
"Я так и думал." (C) Администратор из Half-Life 2.
Yours truly, Serguey Zefirov (thesz NA mail TOCHKA ru)