Здравствуйте, Klapaucius, Вы писали:
K>Снижало бы, если бы этот код не проверялся тайпчекером. Но он проверялся. Ведь обобщенный код на хаскеле проверяется для всех типов, а не для конкретных и только после специализации. K>Утверждения о проверке только используемого кода на C++ просто некорректны. Обобщенный код, который используется в другом обобщенном коде не проверяется. Библиотеки в которых вообще код только обобщенный, т.е. в случае C++ непроверяемый — распространенное явление для языков с нормальным параметрическим полиморфизмом.
Ещё раз, "использование кода" — это генерация из него исполняемого файла. Компилятор отвечает исключительно за это и благодаря статической типизации не позволяет проникнуть в исполняемый файл ни одной ошибке такого рода. Заниматься же помощью в написание исходников — это не дело компилятора! Этим может заниматься например IDE или ещё какие-то подобные инструменты.
K>Вы действительно не называете их "нетипизированными", однако их отличие от всех прочих систем обобщенного программирования в аспекте типизации вроде как признаете, нет?
Конечно, в C++ и D используется система, позволяющая самые широкие возможности. Ценой за это является отсутствие раздельной компиляции. Ну и ещё местами страшноватый синтаксис и сообщения об ошибках в случае C++.
K>Это, в основном, соответствует действительности, вот только отсутствие раздельной компиляции и вообще генеративная природа параметризации никак не связана с типизированностью. Я же говорю, существует системы обобщенного программирования вроде SML-ных функторов (именно SML-ных, окамловых это не касается) и F#-ных инлайн-функций, которые точно так же меняют проблемы с раздельной компиляцией на производительность как и плюсовые шаблоны, но полностью типизированы.
Это просто у вас такое понимание типизированности. ) При котором вы хотите чтобы компилятор выполнял не только свою прямую работу, но и служил чем-то типа статического анализатора кода.
Re[33]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Klapaucius, Вы писали:
K>Потому, что в императивных языках с кое-какими функциональными фичами лямбды/замыкания используют совсем не так, как в ФЯ, где они основной инструмент. Это определяется в числе прочего и принципиально разным уровнем поддержки. K>Контейнеры с функциями совершенно нормальный случай. См. аппликативные функторы, например.
Контейнеры с функциями как раз попадаются. А вот возврат из нашей функции сразу нескольких замыканий что-то не припомню на практике. Хотя естественно в теории возможно. )
K>Это низкоуровневый код. Если я правильно понял о чем идет речь конечно (о кодогенерации а-ля Александреску).
Причём тут метапрограммирование? ) Я про эти вещи говорил. Так они низкоуровневые значит? А что в вашем понимание является высокоуровневым кодом?
K>Ну так покажите. А то я опять какой-то "страшный" монадический код покажу и опять окажется, что весь ужас в еще непоказанном. Нету у меня чувства жуткого монадического кода — тут без эксперта по ужасам монад никак не получится.
Я писал это Ikemefula, который просто не в курсе какая жуть следует за использованием State int вместо int. Вы же прекрасно в курсе о чём речь, просто упорно считаете это нормальным. )))
Re[34]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
_>Причём тут метапрограммирование? ) Я про эти вещи говорил. Так они низкоуровневые значит? А что в вашем понимание является высокоуровневым кодом?
K>>Ну так покажите. А то я опять какой-то "страшный" монадический код покажу и опять окажется, что весь ужас в еще непоказанном. Нету у меня чувства жуткого монадического кода — тут без эксперта по ужасам монад никак не получится.
_>Я писал это Ikemefula, который просто не в курсе какая жуть следует за использованием State int вместо int. Вы же прекрасно в курсе о чём речь, просто упорно считаете это нормальным. )))
Цже пошел второй месяц обсуждения, а ты никак эту жуть не покажешь Не боись, я не пугливый, переживу
Re[33]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Klapaucius, Вы писали:
EP>>1. Я вам привёл уже несколько вариантов решения UFP в C++, в том числе GC. О чём тут ещё спорить? K>Из которых ни одно решение кроме консервативного GC доступность не гарантирует,
Копирование, перемещение и refcounting тоже гарантирует доступность.
K>а консервативный GC не обладает приемлемыми с практической точки зрения свойствами.
Есть точные GC — но они менее автоматизированные чем консервативные. При использовании точных нужно заменять T* на gc_ptr<T>, etc.
EP>>3. Вариант решения UFP с ресурсами (называйте как хотите — UFP не UFP, но то что проблема подобная это факт) в языках (с позиции которых был наезд "даже Upward Funarg Problem не решена") продемонстрирован не был. Запрет — это не решение. K>Я же говорю, уберите скобки-using-и и будет UFP. Скобки нужны для prompt finalization.
Даже если не требовать prompt finalization, получается что нет никакого UFP-автоматизма — нельзя просто захватить какую-то переменную, нужно ещё и cкобки убирать, которые могут быть выше замыкания несколькими уровнями (что и было в исходном примере).
Re[35]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Ikemefula, Вы писали:
I>Цже пошел второй месяц обсуждения, а ты никак эту жуть не покажешь Не боись, я не пугливый, переживу
Ну вообще то там была речь про IO (где всё ещё хуже), а не ST... Хотя разница не особо принципиальна. Просто ST во-первых можно не особо много использовать, а во-вторых есть средства для локализации ужаса. В случае же IO в обычном приложение всё наоборот.
Если есть желание вникнуть, то мне очень понравился один учебник (и это при том, что сам язык не понравился). Одновременно и с хорошим языком и очень подробный (если весь прочитать). Сейчас поищу ссылки на соответствующие разделы...
Значит вот теория про ST с примерами. После прочтения этого, должно стать очевидным, что неконстантная ссылка в Хаскеле — это что-то из области ада (в сравнение с другими языками). А пример qsort'а там вообще просто на загляденье... )))
А вот хорошее описание того, как автор пытается бороться с тем, во что вырождается Хаскель при столкновение с реальностью (интенсивным взаимодействием с внешним миром). Здесь уже больше про IO. Кстати, замечу, что автор тоже отделяет страшный монадный код от классического (который в реальности наверное только в учебниках и бывает) и называет его "псевдо-Haskell".
Re[33]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Klapaucius, Вы писали:
EP>>Над этим числодроблением можно точно также надстроить абстракции (бесплатные/дешёвые), более близкие к конкретной предметной области. Например Eigen+МКЭ. K>Будто бы МКЭ какое-то особенное числодробление.
Внутри обычное числодробление, которым занимается Eigen. А снаружи — МКЭ-DSL, который генерирует матрицы элементов для перемалывания.
То есть над одним DSL — Eigen, надстраивается другой — МКЭ. Уровень абстракции повышается, а runtime penalty минимальный, если вообще присутсвует.
K>>>В большинстве низкоуровневого кода — да, в большинстве идиоматического ФП-кода — нет. EP>>Например C#/Java — это какие по-вашему? Низкоуровневые? K>Разговор был вообще-то про ФП, с натяжкой ФЯ можно разве что C# посчитать.
Вы постоянно пытаетесь противопоставить "ФП" и "низкоуровневый код". Как-будто только ФП это высокий уровень. Поэтому я и спросил про C#/Java.
EP>>То есть весь вопрос в том, насколько часто у дорогих абстракций нет дешёвых альтернатив. K>Полноценных альтернатив у дорогих абстракций не бывает никогда — иначе они (дорогие абстракции) никогда не вышли бы из областей больного воображения в реальный мир.
Конкретный пример — runtime reflection. В большинстве случаев достаточно compile-time reflection.
У runtime reflection огромный overhead, а у compile-time — нулевой.
EP>>Память плоская только в пределах массива/структуры. K>И где же у указателя эти "пределы"?
В ISO C++.
За этими пределами — here be dragons, в виде undefined behaviour.
Re[41]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Sinclair, Вы писали:
EP>>>>Другой вопрос насколько это необходимо. В том же Node.js можно точно также отстрелить себе ногу. S>>>Лично я никогда не позиционировал Node.js как панацею надёжности. EP>>Ну да — так там её просто нет, но тем не менее это не мешает его использовать. S>Я пока скептически отношусь к Node.js. В своё время казалось, что тяжеловесные ОРМ — это ответ на все вопросы. А потом внезапно выяснилось, что они создают больше проблем, чем решают. Вот и Node.js — интересный эксперимент. Году к 2020 посмотрим, что из него имеет смысл вписывать в скрижали, а что окажется смешным заблуждением наивных пропонентов.
ИМХО, Node.js зацепился только за счёт инфраструктуры и рекламы ("buzzwordish"). Ничего особенного там нет, тем более для надёжности. Поначалу даже не предлагалось никакого решения для распутывания лапши callback'ов.
EP>>Если нет возможности сделать вечный цикл — то это не аналог while. S>А для чего вам вечный цикл?
Для полноты по Тьюрингу.
Re[36]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
_>Значит вот теория про ST с примерами. После прочтения этого, должно стать очевидным, что неконстантная ссылка в Хаскеле — это что-то из области ада (в сравнение с другими языками). А пример qsort'а там вообще просто на загляденье... )))
Quick Sort там, кстати, далёк от оригинального — вместо bidirectional partition Тони Хоара, используется forward partition Нико Ломуто.
Например разница в том, что для массива эквивалентных элементов bidirectional вариант даёт Θ(N*log(N)), а forward — Θ(N^2).
Если же делать bidirectional partition — то код там будет ещё красивее
Re[36]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
_>Значит мы пишем наши функции всё же монадным способом, а потом пакуем их в копирующие обёртки, с расчётом на то, что оптимизация выкинет эти обёртки на месте стыка.
Это просто потому, что затребованное вами поведение (с многочисленными проходами по одному мутабельному массиву) воспроизводится оптимизациями, описанными в пакете vector для монадического кода. Нелифтнутый код, с иммутабельными массивами оптимизируется так, как я показал выше — там в типичном конвейере будут разные типы промежуточных значений между "стадиями", а значит в общем случае писать в один массив много раз не получится — нужно соединять n проходов в один и тогда уже писать. Поскольку оптимизации это или правила перезаписи в библиотеке или обычный код (в случае плагинов) — реализовать можно разные преобразования и разными способами. Это просто демонстрация того, что компиляторы, оптимизирующие ФП-код, реально существуют, что собственно и требовалось.
_>Т.е. автоматически (обычным красивым кодом) добиться быстродействия в Хаскеле нельзя, но если специально заняться этим вопросом, то руками можно много чего оптимизировать...
Где тут ручная оптимизация и где некрасивый код? Вручную ничего не оптимизировано — наоборот — все автоматически.
_>Ну вообще то одно лишнее копирование всё же есть. Но я понимаю о чём вы — что при 10-и функция будет всё равно это же одно лишнее копирование, а не 10.
Это "лишнее копирование" уйдет точно также как и остальные, когда функция из примера сфъюзится с первоначальным источником массива. Т.е. если вы в хаскельный код даете указатель, то именно этот указатель такая функция и будет двигать и писать в память, на которую он указывает.
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[56]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
K>>Утверждения о проверке только используемого кода на C++ просто некорректны. Обобщенный код, который используется в другом обобщенном коде не проверяется. Библиотеки в которых вообще код только обобщенный, т.е. в случае C++ непроверяемый — распространенное явление для языков с нормальным параметрическим полиморфизмом.
_>Ещё раз, "использование кода" — это генерация из него исполняемого файла.
Нет, "использование кода" — это использование обобщенного кода для написания другого обобщенного кода.
_>Компилятор отвечает исключительно за это и благодаря статической типизации не позволяет проникнуть в исполняемый файл ни одной ошибке такого рода. Заниматься же помощью в написание исходников — это не дело компилятора! Этим может заниматься например IDE или ещё какие-то подобные инструменты.
Непонятно, откуда взялось такое ограничение. Во всех языках с обобщенным программированием (кроме C++ и клонов) именно компилятор является легковесным верификатором кода, в том числе и обобщенного. Если плюсовой компилятор не может этого делать — это проблема именно плюсового компилятора и его пользователей, а не какое-то общее правило для всех компиляторов.
_>Конечно, в C++ и D используется система, позволяющая самые широкие возможности. Ценой за это является отсутствие раздельной компиляции. Ну и ещё местами страшноватый синтаксис и сообщения об ошибках в случае C++.
Трейдофф между раздельной компиляцией и производительностью получаемого кода понятен и уже обсужден — проблема же в том, что обобщенный код не проверяется, хотя никаких препятствий для этого нет (если, конечно, проектировать средства обобщенного программирования типизированными с самого начала — потом без нарушения обратной совместимости добавить ее уже затруднительно) — никакого компромисса между производительностью и типизированностью не нужно, наоборот, от типизированности для производительности одна польза (по крайней мере, пока у нас завтипов нет).
_>Это просто у вас такое понимание типизированности. ) При котором вы хотите чтобы компилятор выполнял не только свою прямую работу, но и служил чем-то типа статического анализатора кода.
Служить статическим анализатором кода — прямая работа компиляторов всех типизированных языков. Компилировать без статического анализа не в рантайме вообще довольно затруднительно, да и мы же вроде не трассирующие JIT-компиляторы бестиповых языков тут обсуждаем?
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[37]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Klapaucius, Вы писали:
K>Где тут ручная оптимизация и где некрасивый код? Вручную ничего не оптимизировано — наоборот — все автоматически.
Мы перешли от обычного задания функций (как было в моём примере, который, как я понимаю, не оптимальный совсем) на монадное. И плюс нам надо конструировать дополнительные обёртки вокруг наших функций, наоборот устраняющие монадность. Это и есть ручная оптимизация.
K>Это "лишнее копирование" уйдет точно также как и остальные, когда функция из примера сфъюзится с первоначальным источником массива. Т.е. если вы в хаскельный код даете указатель, то именно этот указатель такая функция и будет двигать и писать в память, на которую он указывает.
Что-то мне это не очевидно. Я пока понял, что оно оптимизируется только при условие, что в нашу тестовую функцию передаётся результат вызова "new".
Re[57]: Есть ли вещи, которые вы прницпиально не понимаете...
_>>Ещё раз, "использование кода" — это генерация из него исполняемого файла. K>Нет, "использование кода" — это использование обобщенного кода для написания другого обобщенного кода.
Это уже использование кода человеком, а не компилятором.
K>Непонятно, откуда взялось такое ограничение. Во всех языках с обобщенным программированием (кроме C++ и клонов) именно компилятор является легковесным верификатором кода, в том числе и обобщенного. Если плюсовой компилятор не может этого делать — это проблема именно плюсового компилятора и его пользователей, а не какое-то общее правило для всех компиляторов.
Почему ограничение? ) Если вам хочется включить в свой компилятор какую-то дополнительную функциональность (вот тот же clang ещё много чего умеет, кроме просто компиляции), то никто этого не запрещает. Только не надо тогда называть эту дополнительную возможность типизацией и как следствие считать её обязательной.
K>Трейдофф между раздельной компиляцией и производительностью получаемого кода понятен и уже обсужден — проблема же в том, что обобщенный код не проверяется, хотя никаких препятствий для этого нет (если, конечно, проектировать средства обобщенного программирования типизированными с самого начала — потом без нарушения обратной совместимости добавить ее уже затруднительно) — никакого компромисса между производительностью и типизированностью не нужно, наоборот, от типизированности для производительности одна польза (по крайней мере, пока у нас завтипов нет).
Если мы говорим про C++, то там обобщённый код полностью проверяется, но только на момент использования. На мой взгляд этого более чем достаточно для уверенности в корректности созданного ПО.
K>Служить статическим анализатором кода — прямая работа компиляторов всех типизированных языков. Компилировать без статического анализа не в рантайме вообще довольно затруднительно, да и мы же вроде не трассирующие JIT-компиляторы бестиповых языков тут обсуждаем?
Да, для кода используемого для генерации исполняемого кода. А не для кода, просто лежащего где-то на диске.
Re[36]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
_>Значит вот теория про ST с примерами. После прочтения этого, должно стать очевидным, что неконстантная ссылка в Хаскеле — это что-то из области ада (в сравнение с другими языками).
Перевожу для тех кто читает твои сообщения — "ужос, ужос, ужос" включая "чтото из области ада" есть просто многолетняя привычка к плюсам и основаные на ней эмоции.
>А пример qsort'а там вообще просто на загляденье... )))
Ужос — синтаксис не как в С++
Re[37]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Ikemefula, Вы писали:
I>Перевожу для тех кто читает твои сообщения — "ужос, ужос, ужос" включая "чтото из области ада" есть просто многолетняя привычка к плюсам и основаные на ней эмоции.
Я вообще то много какие языки использую и ещё большее количество знаю. Но нигде, кроме указанного случая, не требуется подобный дикий код для использования банальной ссылки.
Re[38]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
I>>Перевожу для тех кто читает твои сообщения — "ужос, ужос, ужос" включая "чтото из области ада" есть просто многолетняя привычка к плюсам и основаные на ней эмоции.
_>Я вообще то много какие языки использую и ещё большее количество знаю. Но нигде, кроме указанного случая, не требуется подобный дикий код для использования банальной ссылки.
Я не вижу там никакого дикого кода, процитируй его сюда пожалуйста
Re[42]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>ИМХО, Node.js зацепился только за счёт инфраструктуры и рекламы ("buzzwordish"). Ничего особенного там нет, тем более для надёжности. Поначалу даже не предлагалось никакого решения для распутывания лапши callback'ов.
+1.
S>>А для чего вам вечный цикл? EP>Для полноты по Тьюрингу.
А для чего вам полнота по Тьюрингу?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[42]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>ИМХО, Node.js зацепился только за счёт инфраструктуры и рекламы ("buzzwordish"). Ничего особенного там нет, тем более для надёжности. Поначалу даже не предлагалось никакого решения для распутывания лапши callback'ов.
В ноде очень простой и понятный апи, нормальная модульная система и функции. От джаваскрипта достается песочница. Все вместе это дает довольно простую и дешовую асинхронщину.
В ноде и не нужно ничего для распутывания колбеков. Это задача языка или модулей. Сейчас всё не хуже, чем в питоне
Cкажем, вот такой пример один к одному перегоняется в джаваскрипт
Здравствуйте, Sinclair, Вы писали:
S>а функции вида A G(B b) лифтятся до Monad<A> G(Monad<B>) в два приёма: сначала строится функция Monad<A> G'(B b) при помощи unit, а уже потом bind.
Это называется fmap.
Re[34]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
_>Контейнеры с функциями как раз попадаются. А вот возврат из нашей функции сразу нескольких замыканий что-то не припомню на практике.
И откуда у вас эти контейнеры с функциями берутся, если вы их не из функций возвращаете?
_>Причём тут метапрограммирование? ) Я про эти вещи говорил.
А причем тут уровни кода тогда? Если речь не о воплощении шаблонов проектирования с помощью каких-то инструментов метапрограммирования.
_>Так они низкоуровневые значит? А что в вашем понимание является высокоуровневым кодом?
Я тут писал по соседству, что высокоуровневый код — это такой код, о строительных блоках которого можно рассуждать как о математических объектах (о функциях как о функциях, например) и извлекать из этого какую-то пользу.
_>Я писал это Ikemefula, который просто не в курсе какая жуть следует за использованием State int вместо int. Вы же прекрасно в курсе о чём речь, просто упорно считаете это нормальным. )))
Ну так покажите всем, как это ненормально. Слева все хорошо, справа "ужас-ужас-ужас". Но вы же упорно не хотите этого делать. И понятно почему, потому что рядом с императивным кодом на большинстве языков монадический код смотрится совсем не страшно.
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[38]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
K>>Где тут ручная оптимизация и где некрасивый код? Вручную ничего не оптимизировано — наоборот — все автоматически.
_>Мы перешли от обычного задания функций (как было в моём примере, который, как я понимаю, не оптимальный совсем) на монадное.
Я же объяснил, что это потому, что запрашиваемое вами конкретное поведение (с n-проходов) реально существующая библиотека обеспечивает при оптимизации "монадного" кода, а для остального другое поведение (хотя устранение промежуточных значений тоже происходит и такие преобразования я тоже продемонстрировал). Мы вроде начали с принципиальной возможности таких оптимизаций в реально существующем компиляторе, а теперь оказывается что пока я не напишу библиотеку с какими-то конкретными перламутровыми пуговицами это не засчитывается. Причем, когда я ее напишу, то окажется, что пуговицы опять недостаточно перламутровые и т.д.
_>И плюс нам надо конструировать дополнительные обёртки вокруг наших функций, наоборот устраняющие монадность. Это и есть ручная оптимизация.
Вообще-то это ручная пессимизация в чистом виде. Я вручную создаю лишние копирования, которые компилятор устраняет.
Как раз для того, чтоб это (устранение их компилятором) продемонстрировать.
_>Что-то мне это не очевидно. Я пока понял, что оно оптимизируется только при условие, что в нашу тестовую функцию передаётся результат вызова "new".
И в чем проблема? Почему бы первоначальному источнику не передавать результат обернутый в New?
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll