Здравствуйте, alex_public, Вы писали:
_>Если это состояние хранится в самой функции, то это уже не ФП. А если передаётся в неё как параметр (и при этом естественно является иммутабельным), то никаких проблем.
Если буквально, то состояние никогда не хранится в функции Замыкание, это состояние, которое как бэ хранится в функции. Как бэ — потому что у функции может быть много замыканий.
I>>Иммутабельность нужна для решения проблемы разделяемых ресурсов. Вместо того, что бы придумывать логику владения, синхронизации и тд, делается копия для которой есть гарантия, что все такие же экземпляры будет эквивалентны.
_>Не придумывай. ))) Это всего лишь одно из полезных побочных свойств ФП, а совсем не причина такого устройства.
Я вроде ясно говорю — "иммутабельность нужна для решения" а не "иммутабельность есть причина". Для чего еще нужна иммутабельность — дело десятое.
>Более того, существование подобных плюсов проявилось относительно недавно, когда появилось многопоточное программирование и т.п., хотя языки с таким устройством существовали уже давным давно. )
Недавно это лет 50-60 назад ?
Re[28]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
I>>Каким образом мерить эффективность?
_>Ну да, я не совсем корректно сказал. Речь конечно же про быстродействие кода.
В распределенной системе быстродействие кода каждого из узлов вполне может оказаться незначительной деталью. Пример — берём 1000 узлов и организуем последовательную обработку информации — каждый следующий узел берет всю пачку данных у предыдудщего, обрабатывает отдаёт следующему. Итого — быстродействие на высоте, а работает в один момент только один узел.
То есть, быстродействие кода каждого из узлов всего лишь необходимое условие для некоего минимального уровня выходного сигнала.
I>>ФП ничему не противоречит. Ты путаешь особенности вычислителя и требования ФП.
_>Ты можешь предложить реализацию ФП с не иммутабельными данными? )
Я могу предложить пример вычислителя, где императивный ЯП будет сливать любому ФЯ — это асинхронный вычислитель.
I>>А теперь представь себе распределенное приложение. Внезапно <любой императивный язык> слился весьма бесславно. Ты, конечно, можешь выкрутиться навроде "даже если одна функция написана на С++" значит и всё приложение написано на С++.
_>Что ты подразумеваешь под "распределённым приложением"? Что-то типа MPI? И почему это любой императивный язык тут сливается? )
Я не знаю что такое MPI
Re[60]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, Ikemefula, Вы писали:
I>>Выдай правило, которое расскажет когда же делать эту распаковку, а когда — нет.
_>В смысле когда? Всегда естественно) Ну если конечно эта функция не сводится к комбинации нескольких других такого же типа.
А как быть с функцией, которая уже умеет работать с optional<double> и ей не нужны никакие распаковки ? Заворачивать её в другую фунцию, которая сделает упаковку после распаковки ?
Re[47]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Klapaucius, Вы писали:
K>Это как-то можно раскрыть?
Речь шла про метапрограммирование средствами самого языка (а не внешними средствами).
K>Именно об этом. Ничего удивительного в этом как раз нет. В более-менее нормальных языках такое доступно: K>.. K>Обычное метапрограммирование, параметрический полиморфизм тут не причем.
Ну да, я в том сообщение прямо так и написал, что уже отвлёкся на другую тему.
А МП у нас действительно есть во многих языках, но очень разного уровня. И уровень D я мало где видел, разве что в Nemerle ещё сильнее, но там только МП и есть по сути, так что практической пользы от этого пока нет. Ну и макросы Лиспа конечно же, но это уже совсем другая история. )))
Да, так вот, возвращаясь к другим областям... Если у языка есть развитое МП, то даже если в нём и не заложены изначально некоторые возможности, то их практически всегда можно добавить, используя МП.
K>Это точно про D? Он вроде супербыстродействием никогда похвастать не мог.
Сам D конечно помедленнее чем C/C++, хотя быстрее Java/C#. Но здесь речь вообще не об этом шла. Подразумевалось супербыстродействие в сравнение с вариантом "поставлять тексты на том DSL в конечном приложение и просто запускать рантайм интерпретатор их". Т.е. грубо говоря идёт сравнение вариантов типа PHP или как если бы мы транслировали PHP код в C код и потом вкомпилировали бы их в http сервер. Кстати, интересный нюанс: практически к такому же решению и пришли Фейсбук и Вконтакте на своих серверах, только очень сложным и мучительным путём (например пришлось разрабатывать подмножество PHP и т.п.). А тут у нас всё из коробки работает.
Re[27]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Klapaucius, Вы писали:
EP>>Оставим prompt finalization в стороне. Вот есть у нас using на ресурс в C#, или регион в Haskell — можем ли мы сделать замыкание на идентификатор ресурса (в funarg ведь про идентификаторы речь) и передать это замыкание наверх? K>Ну да. Оставляем prompt finalization в стороне и сразу переходим к prompt finalization!
Неудобно как-то получается, да? Вроде UFP (захват free variable замыканием) — а GC ничем помочь не может
EP>>можем ли мы сделать замыкание на идентификатор ресурса (в funarg ведь про идентификаторы речь) и передать это замыкание наверх? K>В C# можем,
Как? Транзитивно заражая все места использования ручным using'ом?
EP>>можем ли мы сделать замыкание на идентификатор ресурса (в funarg ведь про идентификаторы речь) и передать это замыкание наверх? K>в хаскеле есть средства для предотвращения этого а-ля ST.
ST не работает в Haskell 98, то есть требует расширение?
Потом, предотвращение — это не решение задачи. Вот, например, нужно чтобы работало что-то типа:
import System.IO
main = do
closure <- withFile "test.out" WriteMode $ \f -> do
hPutStr f "ok"
return $ \s -> do
hPutStr f "logging: "
hPutStrLn f s
closure "fail"-- test.out: hPutStr: illegal operation (handle is closed)
как?
EP>>На haskell.org написанно: EP>>[...] EP>>В этой табличке для C++: EP>>support functional programming by supporting first-class function EP>>functional style is NOT the dominant one K>А если я в какой-нибудь вики напишу, что луна из сыра — вы поверите?
В случае с C++ я знаю как и насколько он поддерживает functional programming. Относительно UFP — я вам приводил несколько вариантов решения, причём которые работают не только для памяти.
Этого видимо недостаточно, поэтому я привёл цитату из haskel.org wiki — чтобы сослаться хоть на какой-то авторитет (естественно wiki это не то, но всё же).
K>>>>>>Мы вроде бы в соседней ветке выяснили, что без ленивости комбинирование функций теряет смысл из-за непрактичности. EP>>>>В том примере нужна не ленивость, а monadic код. Ленивость помогла только в одном случае из двух, и как видно в общем случае не позволяет сделать обычный код монадичным. K>>>Ничего не понимаю. Ленивость не делает код монадическим. Она нужна, чтоб функции, полученные как результат комбинации других не делали лишние вычисления/проходы. Т.е. в обсуждаемом случае нужна, чтоб монадический код нормально работал. EP>>Для монады Maybe, ленивость позволяет foldr работать так, как работал бы foldrm. K>Не знаю, что вы подразумеваете под foldrm, foldr работает как foldr, а foldM совсем другая функция: K>[...] K>foldr же в обсуждаемом примере просто расставляет лифтнутые (+) между элементами списка. K>[...] K>Ленивость позволяет не вычислять невостребованное. А левая свертка cons списка востребует все, да еще как!
Так, восстанавливаем контекст:
1. Изначально речь шла про автоматическое преобразование обычного кода в монадический.
2. Implicit лифтированние операторов помогает только в некоторых случаях, и не позволяет получить монадические эффекты в общем случае. Например alex_public показал автоматическое лифтирование в D, так вот — там и foldl и foldr не дают необходимого монадического эффекта для Maybe (будут обрабатываться все элементы, даже если есть Nothing).
3. В Haskell, за счёт ленивости — получается достичь необходимых монадических эффектов за счёт лифтирования в большем классе случаев, но далеко не во всех. Например для foldr+Maybe работает, а для foldl — нет.
Т.е. в общем случае код всё равно придётся переделывать на монадический — ленивость помогает только в некоторых специфичных случаях.
В языках же с call-with-current-continuation: любой код можно сделать монадическим без модификаций (либо нужно сделать минимальные модификации, заменив "x" на "get(x)" — если нет перегрузки всего как в D. И то, такая замена можно потребоваться только в листах call-tree, а не по всему коду). Так вот, в языках с call/cc — и foldl и foldr станут монадическими без изменения структуры foldl/foldr.
4. Вы сказали:
K>Мы вроде бы в соседней ветке выяснили, что без ленивости комбинирование функций теряет смысл из-за непрактичности.
Хотя ничего подобного мы не выясняли
Re[34]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Evgeny.Panasyuk, Вы писали:
I>>2 Замыкания не теряют связь с локальными переменными, никогда, ни при каких случаях, до момента сборки мусора.
EP>Допустим у нас такое определение — ОК. EP>Что делать в случае, когда захватываются ресурсы? (пусть это не относится к UFP по данному выше определению)
Контролировать ресурсы явно, руками. Проблема с ФП в том, что циклические ссылки это норма. Это поначалу просто убивает мозг.
Предположим, ты открываешь ресурс и using разрушит ресурс только когда разрушится замыкание.
Совершенно не ясно как ты собираешься это использовать из за наличия циклических ссылок.
Варианты
1 "вон это замыкание из вон той функции использовать только один раз и сразу разрушать"
2 "вот это замыканиние из вон той функции не трогаем, как отсохнет, само отвалится, хрен его знает как это происходит, но на прошлой неделе это происходило в среднем за 500мс"
Других нет, точнее, они сводятся к двум этим
1 — если используешь один раз, это равносильно вызову в правильном месте
2 — если используешь много раз, получаешь хрень с занятым ресурсом и недетерминированым временем использования. То есть разрушение как бы детерминировано — но вот сколько ресурс будет использовася, хрен его знает, например сильно вряд ли ты просчитаешь сложную рекурсию и тд и тд. Но как только перестанет использоваться — сразу разрушится. Очевидно, этот вариант есть просто некорректный код.
Итого — если делать "как в С++" то надо бороться с циклическими ссылками и желательно что бы эти циклические ссылки искал компилятор, а вот компилятор этого как раз и не умеет. То есть, в итоге пришли к ручному управлению, когда, казалось бы, нужна была автоматизация. Все чего добились — ручная неявная работа с ресурсами.
В С++ придется следить за циклическими ссылками, приседать, обрезать и тд и тд и тд и всё это руками, но ресурсы будут освобождаться неявно. То есть, руками задаёшь стратегию использования, а вызов произойдет неявно.
Что предлагает ФП — работа с ресурсом делается в изолированом контексте. Нужно думать не о ресурсах, а о результатах операций, а ресурсы использовать унутре каждой из операций. И разумеется явно, руками.
В ФП не надо следить за циклическими сслыками, не надо приседать, обрезать и тд и тд. Делаешь всё как с другими функциями — комбинируешь, вызываешь, параметризуешь и тд. Ресурсами управляешь руками — задаёшь руками стратегию использования по месту вызова, в этом случае вызов разрушения будет сделан неявно.
Итого — оба варианта на деле означают одно и то же — ручной контроль ресурсов. Отдельно можно поговорить про аггрегирование.
Re[29]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Ikemefula, Вы писали:
I>>>Это цифры с потолка. Эрланг показывает и доказывает что твои рассуждения ошибочны. EP>>Какие именно рассуждения, и как он доказывает? I>На нём пишутся распределенные системы, внезапно !
И как это доказывает то, что он работает не медленнее чем аналогичный код на императивном языке?
I>Эрланг собтсвенно и начал с того, что порвал С++ в распределенных приложениях для телекоммуникаций.
Erlang рулит в первую очередь из-за инфраструктуры, а не из-за самого языка. Точно также как рулит и node.js за счёт инфраструктуры.
EP>>Кстати, про Erlang — выше приводили пример "идиоматичного ФП кода": EP>>
EP>>f = 0 : 1 : zipWith (+) f (tail f)
EP>>
попробуй изобрази его на Erlang. EP>>Да, и по-твоему Erlang это чистый ФП? I>Это скучно.
Конечно, мы же обсуждаем чистые ФП и эффективность их мэппинга в железо. Если тебе скучно — то я
Кстати, ранее в обсуждении утверждалось что ленивость — это пища ФП (весьма тормозная). И пример с zipWith выше как раз и использует ленивость. Но в Erlang'е никакой ленивости нет — к чему бы это?
EP>>Устроен танковый батальон естественно не как танк, но без танков нет батальона. Ты что сказать-то хотел своей метафорой? I>Я говорю про отношение часть-целое и характеристики составляющих. У узла узкое место процессор и система ввода-вывода, а у распределенной системы узким местом будет не процессоры и ввод-вывод,
У распределённых число-дробилок в большинстве случаев узким местом будет как раз процессор.
I>а отзывчивость по причине корректности-качества работы диспетчера, которые, в свою очередь, могут никак не зависеть ни от процессора ни от ввода-вывода.
А диспетчер где исполняется? На каком-то чудесном ФП-железе?
I>>>Ты не заметил лямбды в С++ ? Чудеса ! EP>>Это не чистое ФП, а как раз полезные его элементы. И "влазло" оно очень давно. I>Ажно с первых версий stl.
STL это только конкретный известный пример.
EP>>См. например STL — там же кругом value semantics (привет referential transparency) и higher order functions. I>Вот-вот.
Что "вот-вот"? Я же говорю — использование элементов ФП это хорошо.
I>Сколько лет stl ?
Около 20.
Re[25]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Klapaucius, Вы писали:
K>ОК, разделять данные между версиями в теории не обязательно. Но никакой специфики языка тут нет. В библиотеках для ФЯ эти структуры реализуются так, что данные разделяются.
Вот вот. Собственно говоря, из-за иммутабельности данных в ФП языках вообще нет понятия ссылки, как её понимают в C++ (поменяем данные в одном месте кода и это уловил код в другом месте), а есть только копирование (то, что внутри оно может оптимизироваться через ссылки, значения не имеет). Поэтому:
1. Непонятно с чего вы требуете от C++ наличия [&] вверх по стеку, в то время как чистые ФП языки не имеют этого даже вниз по стеку? Собственно сама конструкция & — это признак скорее императивного языка. Да, и кстати [&] вверх по стеку в C++ тоже есть — shared_ptr. Только это получается нужно в основном для той редкой ситуации, которая в ФП языках вообще запрещена.
2. Непонятно почему вы пренебрегаете новой возможностью C++, обеспечивающей возможность осуществлять "копирование из покидаемой области" с нулевыми накладными расходами — она же как раз полностью решает проблему эффективности [=], делая его таким же эффективным как в ФП языка?
Вообще, когда вы говорите про & и чистые функциональные языки, то на самом деле подразумевается всего лишь const&, которая отличается от = только быстродействием. Соответственно в ФП у нас имеется = или же const& (оптимизированная версия), вниз и вверх по стеку. А например в C++ мы имеем:
1. = вверх и вниз по стеку естественно.
2. const& вниз по стеку, т.е. оптимизированное = вниз по стеку
3. && (то самое перемещение), т.е. оптимизированное = вверх по стеку
4. & вниз по стеку, причём оно оптимизировано от рождения
5. shared_ptr, как реализация & вверх по стеку
Т.е. C++ предоставляет все возможности ФП языков в этой области, и плюс ещё несколько (пункты 4 и 5) вариантов.
Re[27]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Ikemefula, Вы писали:
I>Если буквально, то состояние никогда не хранится в функции Замыкание, это состояние, которое как бэ хранится в функции. Как бэ — потому что у функции может быть много замыканий.
Если мы говорим про ФП, то там захватываемые величины становятся просто константами. Так что они явно не могут быть состоянием.
Re[29]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Ikemefula, Вы писали:
I>В распределенной системе быстродействие кода каждого из узлов вполне может оказаться незначительной деталью. Пример — берём 1000 узлов и организуем последовательную обработку информации — каждый следующий узел берет всю пачку данных у предыдудщего, обрабатывает отдаёт следующему. Итого — быстродействие на высоте, а работает в один момент только один узел. I>То есть, быстродействие кода каждого из узлов всего лишь необходимое условие для некоего минимального уровня выходного сигнала.
И какое это имеет отношение к неэффективности (по быстродействию) языков с чистым ФП?
I>Я могу предложить пример вычислителя, где императивный ЯП будет сливать любому ФЯ — это асинхронный вычислитель.
Ну предложи) С удовольствием посмотрим. )
_>>Что ты подразумеваешь под "распределённым приложением"? Что-то типа MPI? И почему это любой императивный язык тут сливается? ) I>Я не знаю что такое MPI
Эмммм... Вообще то это самый распространённый инструмент для написания распределённых приложений. Вот http://ru.wikipedia.org/wiki/Message_Passing_Interface ссылочка. Кстати, надо пояснять на каком языке там основные реализации?)))
Хех, мне теперь даже страшно предположить, что ты имел в виду под "распределёнными приложениями", если при этом не в курсе про MPI... )
Re[61]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Ikemefula, Вы писали:
I>А как быть с функцией, которая уже умеет работать с optional<double> и ей не нужны никакие распаковки ? Заворачивать её в другую фунцию, которая сделает упаковку после распаковки ?
Вот как раз такие функции и остаются) Плюс "голые" (без optional вообще). Про это и речь. ) Ты похоже уже запутался в нашей с Синклером дискуссии. Он то хотел вообще третий вид функций привлечь (как раз которые для монад только)... )))
Re[30]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
_>И какое это имеет отношение к неэффективности (по быстродействию) языков с чистым ФП?
Непосредственное — эффективность языка зависит от вычислителя. В императивных языках нет ничего для асинхронщины. Вообще ничего.
I>>Я могу предложить пример вычислителя, где императивный ЯП будет сливать любому ФЯ — это асинхронный вычислитель.
_>Ну предложи) С удовольствием посмотрим. )
Уже.
_>Эмммм... Вообще то это самый распространённый инструмент для написания распределённых приложений. Вот http://ru.wikipedia.org/wiki/Message_Passing_Interface ссылочка. Кстати, надо пояснять на каком языке там основные реализации?)))
Ты снова про производительность отдельного нода и его АПИ
_>Хех, мне теперь даже страшно предположить, что ты имел в виду под "распределёнными приложениями", если при этом не в курсе про MPI... )
Я не в курсе твоих аббревиатур. Эрланг в свое время порвал С++, странно что ты этого не знаешь.
Re[28]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
I>>Если буквально, то состояние никогда не хранится в функции Замыкание, это состояние, которое как бэ хранится в функции. Как бэ — потому что у функции может быть много замыканий.
_>Если мы говорим про ФП, то там захватываемые величины становятся просто константами. Так что они явно не могут быть состоянием.
Это чушь. Поведение не реализуется без состояния. А ФП, мягко говоря, ничем не мешает описывать поведение, более того, активно помогает.
Re[30]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
_>>>Что ты подразумеваешь под "распределённым приложением"? Что-то типа MPI? И почему это любой императивный язык тут сливается? ) I>>Я не знаю что такое MPI
_>Эмммм... Вообще то это самый распространённый инструмент для написания распределённых приложений. Вот http://ru.wikipedia.org/wiki/Message_Passing_Interface ссылочка. Кстати, надо пояснять на каком языке там основные реализации?)))
Здравствуйте, Evgeny.Panasyuk, Вы писали:
I>>>>Это цифры с потолка. Эрланг показывает и доказывает что твои рассуждения ошибочны. EP>>>Какие именно рассуждения, и как он доказывает? I>>На нём пишутся распределенные системы, внезапно !
EP>И как это доказывает то, что он работает не медленнее чем аналогичный код на императивном языке?
Код никого не интересует. Интересуют выходные характеристики конечной системы.
I>>Эрланг собтсвенно и начал с того, что порвал С++ в распределенных приложениях для телекоммуникаций.
EP>Erlang рулит в первую очередь из-за инфраструктуры, а не из-за самого языка. Точно также как рулит и node.js за счёт инфраструктуры.
Это инфраструктуру без подобного языка заюзать невозможно, в принципе.
I>>Это скучно.
EP>Конечно, мы же обсуждаем чистые ФП и эффективность их мэппинга в железо. Если тебе скучно — то я
Это тебе интересно обсуждать ислючительно мапинг в железо.
EP>Кстати, ранее в обсуждении утверждалось что ленивость — это пища ФП (весьма тормозная). И пример с zipWith выше как раз и использует ленивость. Но в Erlang'е никакой ленивости нет — к чему бы это?
Наверное к тому, что Эрлан это энергичный язык ?
I>>Я говорю про отношение часть-целое и характеристики составляющих. У узла узкое место процессор и система ввода-вывода, а у распределенной системы узким местом будет не процессоры и ввод-вывод,
EP>У распределённых число-дробилок в большинстве случаев узким местом будет как раз процессор.
То есть, ты хочешь сказать, что некоторые распределенные системы есть множество всех распределенных систем ?
I>>а отзывчивость по причине корректности-качества работы диспетчера, которые, в свою очередь, могут никак не зависеть ни от процессора ни от ввода-вывода.
EP>А диспетчер где исполняется? На каком-то чудесном ФП-железе?
Диспетчер выполняется, грубо говоря, сразу на всех узлах.
EP>Что "вот-вот"? Я же говорю — использование элементов ФП это хорошо.
Ты почему то начал спрашивать, когда это ФП попало в нативный код
Re[26]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
_>1. Непонятно с чего вы требуете от C++ наличия [&] вверх по стеку, в то время как чистые ФП языки не имеют этого даже вниз по стеку?
Имеют.
>Собственно сама конструкция & — это признак скорее императивного языка. Да, и кстати [&] вверх по стеку в C++ тоже есть — shared_ptr. Только это получается нужно в основном для той редкой ситуации, которая в ФП языках вообще запрещена.
Наоборот, вверх по стеку используется постоянно.
_>2. Непонятно почему вы пренебрегаете новой возможностью C++, обеспечивающей возможность осуществлять "копирование из покидаемой области" с нулевыми накладными расходами — она же как раз полностью решает проблему эффективности [=], делая его таким же эффективным как в ФП языка?
Она ничего не решает, если точнее. Я рядом уже пояснил.
_>1. = вверх и вниз по стеку естественно. _>2. const& вниз по стеку, т.е. оптимизированное = вниз по стеку _>3. && (то самое перемещение), т.е. оптимизированное = вверх по стеку _>4. & вниз по стеку, причём оно оптимизировано от рождения _>5. shared_ptr, как реализация & вверх по стеку
_>Т.е. C++ предоставляет все возможности ФП языков в этой области, и плюс ещё несколько (пункты 4 и 5) вариантов.
Нет никакого "дополнительно", все что ты показал это вверх и вниз.
Re[31]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Ikemefula, Вы писали:
I>Непосредственное — эффективность языка зависит от вычислителя. В императивных языках нет ничего для асинхронщины. Вообще ничего.
А что есть для неё в функциональных языках? )
_>>Ну предложи) С удовольствием посмотрим. ) I>Уже.
Это типа "асинхронный вычислитель"? ) Мне эта фраза ни о чём не говорит вообще. Давай конкретный пример кода или хотя бы статью в вики на описание архитектуры.
I>Ты снова про производительность отдельного нода и его АПИ
Ээээ что что? ) С помощью указанного выше инструмента программируют большинство современных суперкомпьютеров, вычислительных кластеров и т.п. )
I>Я не в курсе твоих аббревиатур. Эрланг в свое время порвал С++, странно что ты этого не знаешь.
Эрланг ничего так язык. Мне всегда нравился Пролог (жаль что в Эрланге от него только синтаксис и остался, без реального наполнения). И модель акторов тоже хороша (правда сейчас её уже начали спокойно использовать и в C++, а D она вообще входит в стандартную библиотеку). Но насчёт "порвал" — это ты мягко говоря преувеличил. ))) Даже в целевой нише Эрланга только небольшая часть софта пишется на нём. Так что он вообще никого не порвал, а пока что просто сумел выжить и даже имеет парочку примеров написания известного софта (только в других языках таких примеров сотни в той же области). В общем его позиция выглядит намного лучше чем у D или Haskell, но о мейнстриме (даже в своей нише!) ему ещё мечтать и мечтать... )))
Re[32]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
I>>Непосредственное — эффективность языка зависит от вычислителя. В императивных языках нет ничего для асинхронщины. Вообще ничего.
_>А что есть для неё в функциональных языках? )
Композиция функций.
_>Это типа "асинхронный вычислитель"? ) Мне эта фраза ни о чём не говорит вообще. Давай конкретный пример кода или хотя бы статью в вики на описание архитектуры.
Я уже раз 100 упомянул, но ты никуда не заглянул. Что изменит 101 раз ?
I>>Ты снова про производительность отдельного нода и его АПИ
_>Ээээ что что? ) С помощью указанного выше инструмента программируют большинство современных суперкомпьютеров, вычислительных кластеров и т.п. )
Ля-ля-ля.
курсе твоих аббревиатур. Эрланг в свое время порвал С++, странно что ты этого не знаешь.
_>Эрланг ничего так язык. Мне всегда нравился Пролог (жаль что в Эрланге от него только синтаксис и остался, без реального наполнения). И модель акторов тоже хороша (правда сейчас её уже начали спокойно использовать и в C++, а D она вообще входит в стандартную библиотеку). Но насчёт "порвал" — это ты мягко говоря преувеличил. )))
Читай историю Эрланга.
>Даже в целевой нише Эрланга только небольшая часть софта пишется на нём.
Эрланг давно вышел из этой ниши.
>Так что он вообще никого не порвал, а пока что просто сумел выжить и даже имеет парочку примеров написания известного софта (только в других языках таких примеров сотни в той же области). В общем его позиция выглядит намного лучше чем у D или Haskell, но о мейнстриме (даже в своей нише!) ему ещё мечтать и мечтать... )))
У него популярность растет и растет и в основном в распределенных приложениях.
Re[62]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, Ikemefula, Вы писали:
I>>А как быть с функцией, которая уже умеет работать с optional<double> и ей не нужны никакие распаковки ? Заворачивать её в другую фунцию, которая сделает упаковку после распаковки ?
_>Вот как раз такие функции и остаются) Плюс "голые" (без optional вообще). Про это и речь. ) Ты похоже уже запутался в нашей с Синклером дискуссии. Он то хотел вообще третий вид функций привлечь (как раз которые для монад только)... )))
Нет, я говорю про то же что и Синклер.
Твоя функция, раз "такие функции и остаются", никакая не универсальная. А нужна универсальная и это возможно только с монадами.
Re[27]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Klapaucius, Вы писали:
EP>>>>Про "неработающие" замыкания в C++ из-за UFP любители GC мне тут уже третий раз говорят, хотя "плюсисты" не имеют с этим проблем. На деле же оказывается что работают, и не только для памяти. K>>>Ну правильно: используют не ФЯ, идиомы не ФП — с чего бы им испытывать с этим проблемы, если все тропы протоптаны там, где их нет. EP>>Нет — речь была не про ФП. K>Да. Разговор был именно о ФП, точнее о том, что усилия необходимые для использования зачаточного фп-стиля в C++ превышают бенефиты от использования зачаточного ФП-стиля.
В выделенном разговор был не про ФП.
EP>>Особенно оно не нужно там, где плохо мэппится в реальное железо. K>ФП, да и вообще высокоуровневый код обычно плохо мэппится на реальное железо. Высокоуровневый код хорошо мэппится на человеческие мозги. Тут именно трейдофф между первым и вторым.
What do I mean when I say that an algorithm does not "impose any performance penalty"? In other words, how do you know that a generic algorithm is efficient? An algorithm is called rel atively efficient if it's as efficient as a nongeneric version written in the same language, and it's called absolutely efficient if it's as efficient as a nongeneric assembly language version.
For many years, I tried to achieve relative efficiency in more advanced languages (e.g., Ada and Scheme) but failed. My generic versions of even simple algorithms were not able to compete with built-in primitives. But in C++ I was finally able to not only accomplish relative efficiency but come very close to the more ambitious goal of absolute efficiency. To verify this, I spent countless hours looking at the assembly code generated by different compilers on different architectures.
I found that efficiency and generality were not mutually exclusive. In fact, quite the reverse is true. If a component is not efficient enough, it usually means that it's not abstract enough. This is because efficiency and abstractness both require a clean, orthogonal design. A similar phenomenon occurs in mathematics: Making a proof more abstract makes it more concise and elegant.
То что где-то дорогие абстракции — не означает что они дорогие везде. Естественно, если использовать связанные списки которые плохо мэппятся в железо, thunk'и которые на ровном месте добавляют меж-потоковую синхронизацию и излишние циклы требующие GC — то всё будет тормозить.
В железе есть: изменяемая память(доступ к которой происходит большими порциями ~64B), многоуровневые кэши, синхронизация между кэшами, изменяемые регистры, стэк (с готовыми инструкциями для работы с ним), указатель на текущую инструкцию и разнообразные переходы. Само собой, если даже самые низкоуровневые абстракции в языке делают вид что ничего этого нет и вносят большое penalty сами по себе — то всё будет тормозить.
EP>>2. UFP — это передача замыкания выше области free variables, так? Free variable может чем угодно, а не только памятью K>Free variable не может быть чем угодно. Это языковая сущность. "Память" — это уже другой, нижележащий уровень абстракции. UFP гарантирует продление жизни языковой сущности. Т.е. объекта File, а не файла, хендлером для которого этот файл является.
Так я об этом и говорю — в языках с GC абстракции скрывающие памяти есть, а для других ресурсов как-то не завезли. Поэтому и оперируют такими низкоуровневыми вещами как "открыть файл получить хэндл", "закрыть хэндл", "открыть хэндл и закрыть в конце этого блока".
Ну да — сам хэндл захватится замыканием, и будет жить как минимум столько же, сколько и само замыкание. Но толку-то от закрытого хэндла?
Например в C# — если какой-то из объектов, где-то в глубине композиции начнёт использовать ресурс как поле, то начнётся ад — вся цепочка объектов становится ресурсами, это означает что требуется добавить новый код во всех местах пользования. Особенно весело будет если мы работаем над библиотекой, которая используется клиентами.
В C++ же абстракция есть для всех ресурсов, и при добавление поля-ресурса зависимый код менять не нужно:
class Foo // used at many places
{
Resource x;
// ...
};
EP>>Работающего [&] не будет даже при включённом GC. Даже при использовании GC нужен будет [=] K>В высокоуровневом языке различие между передачей по ссылке и копированием вообще чаще всего семантически ненаблюдаемо.
import Control.Monad.ST
import Data.STRef
import Control.Monad
foo x = modifySTRef x (+1)
main = print $ runST $ do
x <- newSTRef 0
foo x -- by reference!
foo x -- by reference!
readSTRef x
-- prints 2
А тут что?
Кстати, а зачем используют эту венгерскую ноткацию? Почему не просто "modify" вместо "modifySTRef"?
EP>>Вообще-то вопрос был про то, как в Haskell передать замыкание с ресурсом-free-variable наверх. Region'ы судя по всему это проблему никак не решают, поэтому вопрос остаётся открытым. K>Регионы предотвращают утечку ресурса.
Вопрос в том как передать это замыкание наверх, а не запретить передачу.
EP>>Ну да, нет нормального решения — "бессмысленно" K>Но его нет. То, что вы считаете нормальным решением в условиях высокоуровневого языка нормальным не является.
Естественно — лучше запретить.
K>Связывание управления памятью с управлением дефицитными ресурсами там ни к чему хорошему не приводит.
О каком управлением памятью идёт речь?
В C++ есть объекты, у этих объектов есть lifetime. Объекты могут абстрагировать работу с любым ресурсом — память, файлы, соединения и т.п.
EP>>Это в этом варианте?
K>Более-менее осмысленное решение, это делать функцию вида ЭтоНамНадоЧтобПолучитьРесурс -> (ОткрытыйРесурс -> Результат) -> Результат, которая сначала собирает через второй аргумент функции, которые что-то будут с ресурсом делать, а потом выполняется сама, открывая ресурс, скармливая всем этим функциям и закрывая его. Т.е. те самые брекеты и их развитие вроде pipes-safe и resourcet.
EP>>? K>А в чем вы видите противоречие?
В этом варианте все функции для работы над одним ресурсом должны собраться в одном месте, так?
Что делать в случае когда у нас несколько ресурсов, время жизни которых пересекаются и зависят друг от друга? (решение с использованием одного большого scope — естественно неинтересно)
K>Вы с тем, на что я ссылался ознакомились?
С чем именно? С тем вариантом где хэндлы явно передаются через return? Так вопрос же про возвращение замыкания.