LINUX.ORG.RU

Почему ООП стало более популярным и соответствующие языки и технологии программирования чем то же ФП?

 ,


2

4

Заранее прошу прощения за то, что не в Talks, а сюда. Так получается, что теперь в Talks просто так постить нельзя, нужна некая карма и я должен «страдать» (Почему я не могу писать в раздел Talks? (комментарий)). Я в упор не помню данные своего старого аккаунта. Зарабатывать карму здесь и сейчас у меня нет ни времени, ни возможности, ни необходимости. Почему сюда, а не на другие форумы? Потому что считаю, что здесь обитают люди, которые смогут ответить на вопросы ниже и, возможно, даже, которые застали те самые времена (если конечно те самые люди ещё здесь).

Всем доброго времени суток! Не срача ради, а понимания для. Хочется понять историчность и почему так произошло. Понятно, что сейчас уже стали внедрять функциональные фичи много куда (в те же Java, C++, C# и т.д.). Стало появляться много функциональных языков (в том числе совсем новых). Но почему спустя столько времени? Почему спрашиваю:
- Functional programming has its origins in lambda calculus, a formal system developed in the 1930s (!!!) to investigate computability, the Entscheidungsproblem, function definition, function application, and recursion. Many functional programming languages can be viewed as elaborations on the lambda calculus (отсюда: https://en.m.wikipedia.org/wiki/Functional_programming);
- Lisp появился ажно в 1958 году;
- после лиспа ещё была целая куча функциональных языков (APL, IPL, ML, Miranda, Erlang, etc.);
- C++ в 1985;
- Haskell в 1990;
- Java в 1995;

Сама идея ООП (и то я так понял весьма размытая, каждый понимал (и, кстати, по-моему до сих пор понимает) по-своему) вроде как витала со времени создания самого лиспа, но до конкретных реализаций она добралась ближе к концу 80-х - начала 90-х годов.
(поправьте меня, если не прав)
И это ещё при всём при том, что ФП имеет под собой весьма конкретный математический базис (чего я, пожалуй, не могу сказать про ООП).
Я так понял, что благодаря таким крупным компаниям как Microsoft, Oracle...
Но почему они так сильно повлияли на развитие этих технологий и как именно они это сделали я, честно говоря, не совсем понимаю.
Ок, ладно, тогда железо было не такое как сейчас, памяти было маловато для нормального существования функциональных языков на x86 платформе.
Но ведь была же та же, например, Symbolics, которая вроде бы весьма активно продавала лисп-машины?
Ок, Symbolics развалилась благодаря неблагоприятному стечению обстоятельств и «эффективным» манагерам, но их наработки оказались никому не нужны что ли?
И опять-таки, когда нужное железо появилось почему выбор этих и других крупных компаний пал именно на эти языки?
Почему не на функциональные языки?
Потому что в то время функциональные языки в основном использовались сугубо в академической среде или как?
Или если перефразировать всё вышесказанное словами моего коллеги: «если всё так круто (про ФП), то почему оно ещё не захватило рынок?»

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

Не, ООП языки как правило мульти-парадигм (или как там это у вас по русски).

Да ладно. Java, Smalltalk, Ruby. Как на них писать без ООП? Божественный объект и всё в него?

Я для кого писал собщение? www.linux.org.ru/forum/development/15204387?cid=15205670
Вы сначала определяйте своё ООП, а потом уже оценивайте, что под него попадает, а что - нет. Если говорить про попсовый букет - наследование, инкапсуляция, полиморфизм, то без них вполне пишется, но в жаве будет тяжко - придется на интерфейсах прыгать.

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

Обмен элементов вот:
Конкретно операция //.
...
Тоже вариант. Возможно более оптимизированный судя по количеству unsafe и восклицательных знаков

А, пардон, я затупил, перепутал с комментом. Как говорят нам сорцы (//):
http://hackage.haskell.org/package/array-0.5.4.0/docs/src/Data.Array.Base.htm...
«For most array types, this operation is O(n) where n is the size of the array.»
Происходит этом потому, что создается полная копия массива. Таким образом, средняя сложность quicksort O(n * log n) превращается в O(n*n * log n).

Есть diffarray, у которого эта операция стоит O(1), но у него производительность чтения падает с каждым обновлением.

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

Я другого не понимаю. Почему из коробки map не из multiprocessing

Потому что процессы не бесплатны и не безопасны. Так-то несложно и multiprocessing взять:

from multiprocessing import Pool

def f(x):
    print x*x

if __name__ == '__main__':
    pool = Pool(processes=4)
    pool.map(f, range(10))

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

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

Ну вот все программы на Haskell генерируют программы. Также как все программы для cpp, autogen или m4.

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

Я спрашивал, почему нотация анонимной функции в Раст чужеродна. И чему там быть чужродным? Не перегружена синтаксисом, фигурные скобки есть, что еще надо? А какое отношение к этому вопросу имеют замыкания? И какая разница, что было в первых версиях языка? Интерес представляют только версия 1 и выше, остальные — эксперименты и обкатка идей.

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

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

Всё верно. В Си ты пишешь код, который должен выполняться при выполнении программы. В Haskell ты пишешь что-то вроде

main = mapM_ putStrLn $ map fizz [1..100]

И c точки зрения математики результатом программы является вычисление функции main.

Ни map ни список [1..100] к выполнению программы отношения не имеют, это в терминах Си «макросы». Вот есть язык L++ - также пачка макросов поверх Си++.

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

Есть diffarray, у которого эта операция стоит O(1), но у него производительность чтения падает с каждым обновлением.

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

Здесь та же ситуация, что с for(..) if (..) { ... } против fold . filter . map. В функциональном варианте теоретически имеем два лишних списка. Но на практике Haskell умеет list fusion.

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

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

Твоя проблема заключается в том

Моя проблема в том, что я пытаюсь получить хоть какие-то обоснования от надутого пустозвона, у которого есть только желание высказать свое ИМХО, но нет никакого представления о реальности, о которой это ИМХО высказывается. Лишним тому доказательством служит наезд на собеседника вместо предметного разговора по сути ваших претензий к C++. Или, другими словами, вы трындите о том, в чем не разбираетесь.

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

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

Приведенный тобой кусок кода практически не несет функциональной нагрузки - это тупо одни объявления, которые выполняют функцию запутывания пишушего и читающего этот текст.

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

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

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

Так вот это нужно.

Я же, с моим багажом опыта, могу смело ссать в лицо этим авторам и преподавателям

Корона не жмет? Собственно, после такого захода все ваши пространные рассуждения можно смело отправлять в /dev/null.

Но любопытно, как же вы, со своим «багажом опыта», так жидко обгадились то:

принципиально невозможно сделать быстрый парсер для C++

?

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

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

для эффективного ООП достаточно тупого компилятора, а для эффективного ФП компилятор должен быть достаточно умным

Среднестатистический ЯП, спроектированный вокруг конкретной фон Неймановской архитектуры (которая есть деталь реализации), по умолчанию работает на фон Неймановской архитектуре быстрее (прочих ЯП). No fucking way!

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

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

Всё верно. Однако, если исходить не из ложной дихотомии о существовании лишь ООП и функциональных ЯП, предложенной ТС, не должны ли были победить ЯП, основанные на логике первого порядка. Логикой всяко проще проблему описывать, чем искуственно ограниченными конструктами, навязанными какой-то конкретной архитектурой. По поводу производительности, на каком-то этапе даже железо существовало, запиленное, например, специально под Prolog.

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

Столько бла-бла в ОП не по делу, а вот возьми и представь что-то типа Qt с его сотнями классов и тысячами свойств и методов в функциональном стиле

Столько бла-бла не по делу, а вот возьми и представь что-то типа лошади с её подковами и сбруей в автомобильном стиле.

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

Среднестатистический ЯП, спроектированный вокруг конкретной фон Неймановской архитектуры (которая есть деталь реализации), по умолчанию работает на фон Неймановской архитектуре быстрее (прочих ЯП).

Тем не менее полностью функциональный SQL успешно вытеснил императивные языки в области обработки данных.

Кроме того, умный оптимизирующий компилятор уже сейчас почти всегда даёт более быстрый код по сравнению с ручным написанием фон-Неймановского ассемблера.

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

Тем не менее полностью функциональный SQL успешно вытеснил императивные языки в области обработки данных.

SQL не тьюринг-полный (насколько я знаю). Даже не знаю как на sql можно обрабатывать данные, кроме примитивных трансформаций. Может расскажешь?

anonymous
()

Во-первых, дело не в ФП vs ООП, а в ФП vs императивщина. Поскольку ЦП работает на императивных командах, императивным является ассемблер, а значит императивными становятся мозги большого числа специалистов. В том числе тех, кто участвует в принятии решений, какой язык и стиль использовать. И просто тех, кого пришлось бы переучивать с нуля (а не просто подучить использовать объекты и классы). Помимо мозгов императивными были уже распространённые языки и код на них. Тот же переход от C к C++ вообще мог проходить постепенно

Во-вторых, во времена распространения ООП ФП было менее продвинутым

В-третьих, там есть объективно сложные для восприятия вещи

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

SQL не тьюринг-полный (насколько я знаю).

Почти https://habr.com/ru/post/113165/

Даже не знаю как на sql можно обрабатывать данные, кроме примитивных трансформаций. Может расскажешь?

В 1С расчёт НДФЛ со всеми положенными вычетами и особенностями делается на чистом SQL.

Или вот, например, решение систмы линейных уравнений:

create table matrix(nrow integer, ncol integer, val number);
create table coef(nrow integer, val number);

with mrank as
(
    select count(*) as r
    from coef
),
rankgenerator as
(
    select rownum as rn
    from dual, mrank
    connect by level <= mrank.r
),
matrixfordeterminant as
(
    select rg.rn, matrix.nrow, matrix.ncol,
        case
            when rg.rn = matrix.ncol then coef.val
            else matrix.val
        end as val
    from matrix
    inner join coef on matrix.nrow = coef.nrow    
    cross join
    (
        select rankgenerator.rn from rankgenerator
        union all
        select 0 from dual
    ) rg
),
lengthcount as
(
    select sum(length(rn)) + count(rn) lencnt
    from rankgenerator
),
permutations as
(
    select trim('/' from p) path
    from
    (
        select sys_connect_by_path (rn, '/') p
        from rankgenerator
        connect by nocycle prior rn != rn
    ) gen, lengthcount
    where length(p) = lengthcount.lencnt
),
permutationselements as
(
    select perm.path, rn.rn, to_number(regexp_substr(perm.path, '[^/]+', 1, rn.rn)) el
    from permutations perm
    cross join
    (
        select rownum as rn from dual, mrank connect by level <= mrank.r
    ) rn
),
permutation_sign as
(
    select permutations.path, 
           case
               when
                   mod
                   (
                       sum(permelem_rightmincount.rightmincount),
                       2
                   ) = 0
               then 1
               else -1
           end as psign
    from permutations inner join
    (
        select outer.path,
        (
            select count(*)
            from permutationselements inn
                where inn.path = outer.path
                and inn.rn > outer.rn
                and inn.el < outer.el
        ) rightmincount
        from permutationselements outer
    ) permelem_rightmincount
    on permutations.path = permelem_rightmincount.path
    group by permutations.path
),
determinants as
(
    select rn, sum(mul *
           (case when mod(msign, 2) = 0 then 1 else -1 end) *
           (case when mzero > 0 then 0 else 1 end)) det
    from
    (
        select matrixfordeterminant.rn,
               permutation_sign.psign*exp(sum(ln(abs(case when matrixfordeterminant.val = 0
                                                          then 0.01
                                                          else matrixfordeterminant.val
                                                     end)))) mul,
               sum(case when sign(matrixfordeterminant.val) = -1 then 1 else 0 end) msign,
               sum(case when matrixfordeterminant.val = 0 then 1 else 0 end) mzero
        from matrixfordeterminant
            inner join permutationselements
                on matrixfordeterminant.nrow = permutationselements.rn
                and matrixfordeterminant.ncol = permutationselements.el
            inner join permutation_sign
                on permutation_sign.path = permutationselements.path
        group by matrixfordeterminant.rn, permutationselements.path, permutation_sign.psign
    )
    group by rn
)
select determinants.rn, determinants.det/(select determinants.det from determinants where rn = 0)
from determinants
where determinants.rn != 0
order by determinants.rn

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

В 1С расчёт НДФЛ со всеми положенными вычетами и особенностями делается на чистом SQL.

Или вот, например, решение систмы линейных уравнений:

«больные ублюдки!» (с) :-)

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

SQL не тьюринг-полный (насколько я знаю).

Почти https://habr.com/ru/post/113165/

«Почти». Во-первых, это не sql, а нестандартное раcширение sql (первое что заметил WITH RECURSIVE и FROM RDB$DATA). Во-вторых, по любому быстро упрется на малую длину цикла или глубину рекурсии, что бесконечно далеко до тьюринг-полноты.

Или вот, например, решение систмы линейных уравнений:

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

Видно что ты не разбираешься в том что пишешь/копипаститишь? Эталонный stackoverflow-программист.

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

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

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

Во-первых, это не sql, а нестандартное раcширение sql (первое что заметил WITH RECURSIVE и FROM RDB$DATA).

А кто-то говорил про ANSI SQL. Если брать C++, так там в стандарте даже графического интерфейса и сети нет. Одни нестандартные расширения.

sys_connect_by_path

В приносящей больше всего дохода SQL СУБД эта функция есть.

Видно что ты не разбираешься в том что пишешь/копипаститишь? Эталонный stackoverflow-программист.

Это ты не разбираешься. Пишут на реализациях, а не на стандартах.

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

Во-первых, это не sql, а нестандартное раcширение sql (первое что заметил WITH RECURSIVE и FROM RDB$DATA).

А кто-то говорил про ANSI SQL.

Ты говорил про sql, а не про firebird. А сам показываешь пример для firebird. Что за магическая таблица `RDB$DATA`? С таким же успехом можно дергать системные команды, которые могут в нормальную тьюринг-полноту.

Если брать C++, так там в стандарте даже графического интерфейса и сети нет. Одни нестандартные расширения.

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

sys_connect_by_path

В приносящей больше всего дохода SQL СУБД эта функция есть.

Я знаю субд, к которым можно обращаться с использованием sql, хотя они имеют более мощные языки. Может быть ты пишешь на этом более мощном языке этого субд, на котором можно писать свои тьюринг-полные хранимые процедуры/функции как sys_connect_by_path?

Пишут на реализациях, а не на стандартах.

Ты писал на «функциональном SQL» или императивном pl/sql, который включает как подмножество реализацию sql?

Раз подменяешь реализации (firebird-sql, pl/sql), то подменяй и используемые термины.

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

Что за магическая таблица `RDB$DATA`?

Это когда нужны данные без таблицы. В Oraсle было бы FROM dual, в MSSQL запрос без секции FROM.

на котором можно писать свои тьюринг-полные хранимые процедуры/функции как sys_connect_by_path?

Это не хранимая процедура: https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions164.htm

Ты писал на «функциональном SQL» или императивном pl/sql, который включает как подмножество реализацию sql?

Примеры про машину Тьюринга, линейные уравнение и НДФЛ на функциональном SQL.

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

Ты говорил про sql, а не про firebird

WITH RECURSIVE есть и в Oracle и в PostgreSQL.

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

Ты писал на «функциональном SQL» или императивном pl/sql, который включает как подмножество реализацию sql?

Вот расчёт НДФЛ на полностью функциональном языке в самой используемой в РФ зарплатной программе: https://pastebin.com/q0mpn66J

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

Примеры про машину Тьюринга, линейные уравнение и НДФЛ на функциональном SQL.

Раз ты так настаиваешь на своей «функциональности».

Как только докажешь, что точка запятая ";" - это «функционально», а не императивно. Без предварительно созданных таблиц, функций/процедур (вроде вроде нестандартных sys_connect_by_path) ни один из примеров не работает.

А пример с ндфл - это 100% императивщина.

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

Как только докажешь, что точка запятая ";" - это «функционально», а не императивно.

Она выполняет то же, что let x = .... in в Haskell. Можно сделать всё тоже самое скопировав тексты подзапросов вместо использования временных таблиц.

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

Она выполняет то же, что let x = .... in в Haskell.

:) Так же лениво? Или энергично императивно как в (oca)ml или rust.

Можно сделать всё тоже самое скопировав тексты подзапросов вместо использования временных таблиц.

Так давай, вперед, копипасти. Оценим удобство копипаст-программирования на русском «функциональном эскуеле».

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

:) Так же лениво? Или энергично императивно как в (oca)ml или rust.

С точки зрения семантики SQL — лениво. СУБД имеет право не создавать временную таблицу до тех пор, пока она нигде не используется. В 1С точно лениво: там перед выполнением накладываются условия на результат (какие поля выбираются) и от обратного удаляется весь код, который не используется.

Так давай, вперед, копипасти. Оценим удобство копипаст-программирования на русском «функциональном эскуеле».

Мне лень. Но 5 лет назад в 1С не было временных таблиц, а этот запрос был такой же, но с вложенными подзапросами.

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

С точки зрения семантики SQL — лениво. СУБД имеет право...

:) Кажись, ты путаешь «семантику» и «детали реализации».

Мне лень. Но 5 лет назад в 1С не было временных таблиц, а этот запрос был такой же, но с вложенными подзапросами.

То есть, в начале было более-менее функционально, а сейчас «функциональный эскуель» стал не нужен. Так?

Если так, то почему так расхваливаешь «функциональный эскуель»?

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

:) Кажись, ты путаешь «семантику» и «детали реализации».

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

Для SQL побочными эффектами являются только команды INSERT и UPDATE. Была ли временная таблица после SELECT ... INTO ... или оптимизатор сразу вставил в результат, снаружи определить невозможно.

То есть, в начале было более-менее функционально, а сейчас «функциональный эскуель» стал не нужен. Так?

Да также функционально и осталось. Условно раньше было

r = x*x - y*y + z*y*y + d*x*x
теперь стало
let r1 = x*x
    r2 = y*y
in r = r1 - r2 + z*r2 + d*r1

Вторая программа стала менее функциональной от того, что в ней появились промежуточные имена?

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

Сейчас пишут на мешаниние ФП И ООП.

ФП он про чистые функции, во всяких там явавах и питонах в ФП стиле не особо пишется

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

было

r = x + y

стало

#let
  r1 = x
  r2 = y
  oops = x/0
#in
  r = r1 + r2

Что будет при ленивом и энергичном императивном вычислении?

Упс появился в результате, как бы эквивалентных преобразований, например, ошибка при попытке создания временной таблицы, памяти не хватило, админ нашалил.

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

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

т.е. С++, с тех пор, как в нём появились шаблоны, ФП язык?

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

т.е. С++, с тех пор, как в нём появились шаблоны, ФП язык?

Скажем так, язык шаблонов С++ функциональный.

Впрочем, и сам C++ в том числе функциональный уже тоже (с момента, как в STL появилась algorithm, а g++ научился делать TCO).

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

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

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

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

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

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

Я еще раз подчеркиваю, что эта фраза по сути значит «в C++ вы не сможете предложить способ дать компилятору такое же указание менее многословным способом» - и я подчеркиваю, что я согласен с этим утверждением, и описал, откуда оно произошло. В других языках, прежде всего, нет проблемы того, что библиотеки топчутся друг у друга по головам.
Также я упоминал другую проблему в процитированном куске кода - излишние определения типов. Эта проблема в других языках решается просто и дает намного лаконичнее результат, а именно - типы уточняются по мере необходимости. Причем, это же относится и к тому, что поехавший выше назвал «скриптовуха». То есть, сложные конструкции записываются сложно - простые конструкции записываются просто. В C++ простые конструкции записываются сложно, и сложные конструкции записываются сложно.
Чрезмерная формализация так же вредна, как и недостаточная.

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

https://stackoverflow.com/questions/11338109/gcc-understand-where-compilation... - примерно треть времени компиляции занимает парсинг;
https://stackoverflow.com/questions/28919285/identify-slow-to-compile-function - опять треть времени на парсинг.
Что может затмить медленный парсинг? Правильно, шаблоны:
https://www.spinics.net/lists/gcchelp/msg40206.html - 70 секунд из 130 занято шаблонами, 12 секунд на парсинг меркнут на этом фоне.
Чтобы не было упреков в однобоком отображении ситуации - вот статистика по компиляции программы на десяток строк:
https://aras-p.info/blog/2019/01/12/Investigating-compile-times-and-Clang-fti...
Программа не использует буст, ренжи, или какую-то другую библиотеку - только STL. Тем не менее, парсинг занял 0.6 секунд из 3.6 секунд общего времени компиляции - шаблоны здесь не отсвечивали с их 0.5 секунд.

Для справки - компилятор делфи образца нулевых компилирует примерно миллион строк кода в секунду.

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

SQL не тьюринг-полный (насколько я знаю). Даже не знаю как на sql можно обрабатывать данные, кроме примитивных трансформаций. Может расскажешь?

Я видел своими глазами систему планирования производства на чистом SQL. Если бы мне сейчас сказали, что такое возможно, то я бы ответил - нет, врешь. Она очень медленно работала, конечно, потому что там был перебор огромного кол-ва вариантов через cross join.

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

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

«Почти». Во-первых, это не sql, а нестандартное раcширение sql (первое что заметил WITH RECURSIVE и FROM RDB$DATA)

Уже ответили, но все же: common table expressions являются частью SQL:1999, так что решение вполне стандартно.
К сожалению, стандарт не предусматривает выборку выражения из пустоты - по стандарту ты вынужден создать таблицу с одной записью, и выбирать из нее свое выражение. Здесь есть табличка совместимости разных нестандартных приемов с базами: https://modern-sql.com/use-case/query-drafting-without-table

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

С++, с тех пор, как в нём появились шаблоны, ФП язык?

У него свой мир и свои определения ФП языков. Там уже Си - это чистый функциональный язык.

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

Для справки - компилятор делфи образца нулевых компилирует примерно миллион строк кода в секунду.

Что-то я не то сморозил - 100-200 тыс строк в секунду же.

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

вокруг конкретной фон Неймановской архитектуры

те же GPU - уже не фоннеймановской архитектуры

да и классический CPU c кешом и многопоточностью - тоже

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

Тем не менее полностью функциональный SQL успешно вытеснил императивные языки в области обработки данных.

SQL вполне императивный - там есть классические переменные, циклы на курсорах и прочие прелести

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

SQL вполне императивный - там есть классические переменные, циклы на курсорах и прочие прелести

Не путай SQL и PL/SQL. В SQL всего перечисленного нет.

И функциональный не SQL, а язык запросов SQL. Весь DDL и INSERT/UPDATE/DELETE всё-таки императивны.

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

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

Уже устал повторять: вы упорно не приводите никаких подтверждений своим напыщенным словесам.

Все, что вы можете – это ссылаться на какие-то другие языки. Но даже их вы не можете назвать. Потому, что далее последует очевидный вопрос: а сравниваете ли вы одинаковые по возможностям языки? Вам ведь нужно сравнивать C++ с языками из группы C, Ada, Rust, FreePascal. Вот и попробуйте сравнить по возможностям, чтобы и вариадик-шаблоны были, и шаблоны, параметризуемые скалярами, и специализация шаблонов, и constexpr, и множественное наследование. И гладкая интеграция с C (т.е. с любыми системными API).

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

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

и описал, откуда оно произошло

Это вам так кажется.

Также я упоминал другую проблему в процитированном куске кода - излишние определения типов.

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

Про скорость C++ компиляторов (в частности GCC, который быстрым вообще-то никогда и не был). Вот я для эксперимента натравил g++-8 на своем основном рабочем ноуте на один из файлов, который компилируется порядка 15 секунд. Файл уже отпрепроцессирован, чтобы учитывать только время парсинга:

$ time g++-8 -c -o target/_objs/gcc_8_1_0__x86_64_linux_gnu/release/test_header_prj_rb/test_header/main.o \
-O2 -DNDEBUG -DASIO_HAS_STD_CHRONO -DASIO_STANDALONE -DASIO_DISABLE_STD_STRING_VIEW \
-DHTTP_PARSER_STRICT=0 -DFMT_HEADER_ONLY -fPIC \
-std=c++14 test_header_main.i -ftime-report

Time variable                                   usr           sys          wall               GGC
 phase setup                        :   0.00 (  0%)   0.00 (  0%)   0.01 (  0%)    1381 kB (  0%)
 phase parsing                      :   3.34 ( 19%)   1.35 ( 50%)   4.69 ( 23%)  257150 kB ( 38%)
 phase lang. deferred               :   2.07 ( 11%)   0.47 ( 17%)   2.54 ( 12%)  139104 kB ( 21%)
 phase opt and generate             :  12.61 ( 70%)   0.89 ( 33%)  13.51 ( 65%)  280832 kB ( 41%)
 |name lookup                       :   0.82 (  5%)   0.23 (  8%)   1.12 (  5%)   19720 kB (  3%)
 |overload resolution               :   1.72 ( 10%)   0.40 ( 15%)   1.97 (  9%)  104011 kB ( 15%)
...
 TOTAL                              :  18.02          2.72         20.76         678479 kB

real	0m21.380s
user	0m18.165s
sys	0m2.770s

Там подключаются библиотеки, которые насквозь пронизаны шаблонами + разная околосистемная муть (библиотеки Asio, fmtlib, Catch2). Всего более 180KLOC в препроцессированном файле.

Время парсинга чуть больше 3 секунд на древнем ноутбучном i7-3667u. На коде, в котором шаблонов чуть меньше, чем дохера.

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

eao197 ★★★★★
()
Последнее исправление: eao197 (всего исправлений: 1)

Ну вот тут все такие молодцы, ругают ООП, а вот как не в бредовых фантазиях смоделировать обычный автомобиль и мотоцикл или диод/триод/тетрод/пентод, с нуля изобретать две/пять структур? А смысл, ведь 60% будет общего? Если я могу взять класс и хреначить все как хочется

ponchik-2
()
Ответ на: комментарий от ponchik-2

Ну вот тут все такие молодцы, ругают ООП, а вот как не в бредовых фантазиях смоделировать обычный автомобиль и мотоцикл или диод/триод/тетрод/пентод, с нуля изобретать две/пять структур? А смысл, ведь 60% будет общего? Если я могу взять класс и хреначить все как хочется

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

Но чтобы сделать что-то новое, нужен другой подход. Описать какие есть ресурсы, описать какой нужен результат, попытаться найти процесс, который даст наилучший результат. В программировании это ФП (в широком смысле). В инженерии — ТРИЗ. В этом варианте думать приходится больше, но результат сразу делает все предыдущие решения устаревшими: дредноут, моноплан, тепловоз, ...

Можно пофантазировать на тему развития в стиле ООП военных кораблей от броненосцев, авиации от бипланов и локомотивов от паровозов.

или диод/триод/тетрод/пентод

... и чтобы каждый транзистор содержал в себе триод.

monk ★★★★★
()
Ответ на: комментарий от ponchik-2

Ну вот тут все такие молодцы, ругают ООП, а вот как не в бредовых фантазиях смоделировать обычный автомобиль и мотоцикл или диод/триод/тетрод/пентод, с нуля изобретать две/пять структур? А смысл, ведь 60% будет общего? Если я могу взять класс и хреначить все как хочется

Т.е. без ООП использовать уже существующий код нельзя, функциональщики открывают редактор и начинают писать всё с нуля?

ComradeMajor
()

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

Там вполне активно использовалось ООП а ля CLOS.

korvin_ ★★★★★
()
Последнее исправление: korvin_ (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.