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 развалилась благодаря неблагоприятному стечению обстоятельств и «эффективным» манагерам, но их наработки оказались никому не нужны что ли?
И опять-таки, когда нужное железо появилось почему выбор этих и других крупных компаний пал именно на эти языки?
Почему не на функциональные языки?
Потому что в то время функциональные языки в основном использовались сугубо в академической среде или как?
Или если перефразировать всё вышесказанное словами моего коллеги: «если всё так круто (про ФП), то почему оно ещё не захватило рынок?»

«если всё так круто (про ФП), то почему оно ещё не захватило рынок?»

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

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

анапример? чот они все капец какие скучные.

Из новых книг мне понравилась «Get Programming with Haskell». И кажется, что недавно издали перевод на русский. Хорошая книга для начинающих. Как раз занимательная, где в простой форме излагаются базовые вещи. Часто замечаю, что в 2019 году рекомендуют именно эту книгу.

У меня же одной из любимых по-прежнему является «The Haskell School of Expression». Только я по образованию математик, а не программист, и поэтому у меня личные предпочтения могут быть немного особенными.

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

В языках ФП, как правило, только одно ограничение: обычно нужен GC. Но вот пример Rust показывает, что и это ограничение можно обойти. Правда, Rust получился не то чтобы функциональным, но где-то очень близким. Многим хаскелистам нравится ;)

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

dave ★★★★★
()

просто хайп. прошёл тот, пройдёт и этот.

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

И кажется, что недавно издали перевод на русский

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

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

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

Вот это и есть причина отсутствия ФП в массовом программировании. Написать компилятор, который map/filter/fold сообразит превратить в один цикл гораздо сложнее, чем таблицу виртуальных функций для ООП.

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

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

В языках ФП, как правило, только одно ограничение: обычно нужен GC.

В принципе, не обязательно. Можно все служебные списки хранить на стеке. Как в Форт. Но нужен умный компилятор.

Software Transactional Memory

Никто не мешает её использовать в других языках от Си до Джавы.

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

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

Так и объектно-ориентрованный — очень сильное ограничение. И даже структурное программирование. Если писать без ограничений, код быстро перестаёт быть понимаемым и в нём больше случайных ошибок.

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

Потому «hello world» на хаскеле - это элементарный пример нечистой программы.

То есть ты согласен, что утверждение «в ФП нет никакого состояния мира» ложно?

Как они элементарные конструкции завернули в монады и превратили в сложнопонимаемое нечто - это один из примеров.

Зря ты так. Монада позволяет очень удобно описывать свойства сразу куска кода. Действия (значения с типом IO a) можно хранить в любых структурах данных и компоновать в нужном порядке непосредственно перед возвратом в main. Можно писать в монаде MonadError и автоматически получить механизм обработки ошибок. Или в монаде Cont и получить продолжения.

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

элементарные конструкции завернули в монады и превратили в сложнопонимаемое нечто

Это в ООП принято элементарные конструкции в сложнопонимаемое нечто превращать:

Haskell:

fizz n | n `mod` 15 == 0  = "FizzBuzz"
       | n `mod` 3  == 0  = "Fizz"
       | n `mod` 5  == 0  = "Buzz"
       | otherwise        = show n

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

ООП Java:

package com.seriouscompany.business.java.fizzbuzz.packagenamingpackage.impl;

import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.seriouscompany.business.java.fizzbuzz.packagenamingpackage.impl.parameters.DefaultFizzBuzzUpperLimitParameter;
import com.seriouscompany.business.java.fizzbuzz.packagenamingpackage.interfaces.FizzBuzz;
import com.seriouscompany.business.java.fizzbuzz.packagenamingpackage.interfaces.parameters.FizzBuzzUpperLimitParameter;

public final class Main {

	public static void main(final String[] args) {
		final ApplicationContext context = new ClassPathXmlApplicationContext(Constants.SPRING_XML);
		final FizzBuzz myFizzBuzz = (FizzBuzz) context.getBean(Constants.STANDARD_FIZZ_BUZZ);
		final FizzBuzzUpperLimitParameter fizzBuzzUpperLimit = new DefaultFizzBuzzUpperLimitParameter();
		myFizzBuzz.fizzBuzz(fizzBuzzUpperLimit.obtainUpperLimitValue());

		((ConfigurableApplicationContext) context).close();

	}

}
и в зависимостях пачка библиотек.

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

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

Спец либы вполне себе параллелят, но происходит это за пределами питона, а не внутри него.

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

Советую все же прочитать хороший учебник по хаскелю перед тем, как нести пургу о нем. Или чтобы понимать термины.

Это мой код (большей частью): https://pastebin.com/kP5xjCqq
Какие учебники я должен читать?

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

Я изменил файл - изменились результаты чтения. Ты можешь называть чистой функцию с побочными эффектами, можешь себя Рокфеллером называть - мне какое дело? Многие функции, возвращающие контейнер IO, грязные и реализованы на Си - для этого их изолировали в IO, который нельзя никакой функцией очистить, в отличие от тех же списков или Maybe.

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

я не увидел «обоссывания» моего первого аргумента - я не вижу вообще попытки ответной аргументации

Какого аргумента? У вас не было аргументов от слова совсем, было ваше личное мнение.

Это тебе тоже было: https://pastebin.com/kP5xjCqq
https://github.com/ericniebler/range-v3/blob/master/include/range/v3/numeric/...
https://github.com/ericniebler/range-v3/blob/master/include/range/v3/view/sli...

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

прочитаешь хорошую книгу

анапример? чот они все капец какие скучные.

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

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

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

Твоё понимание ООП верное, а у меня странное, я верно понимаю?

У меня нет никакого своего определения. ООП - это очень странная вещь, иррациональная, эдакая красная тряпка для быка - на нее бегут с ошалелыми глазами, о чем я и писал изначально:
www.linux.org.ru/forum/development/15204387?cid=15205670

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

В языках ФП, как правило, только одно ограничение: обычно нужен GC. Но вот пример Rust показывает, что и это ограничение можно обойти. Правда, Rust получился не то чтобы функциональным, но где-то очень близким.

Раст не является ФП языком, а низкоуровневым императивным, потому сборщик мусора ему не нужен.

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

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

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

Вот это и есть причина отсутствия ФП в массовом программировании. Написать компилятор, который map/filter/fold сообразит превратить в один цикл гораздо сложнее, чем таблицу виртуальных функций для ООП.

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

То есть в функциональном стиле легче писать программы, легче читать результат.

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

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

Это тебе тоже было: https://pastebin.com/kP5xjCqq

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

Ну и еще раз, специально для вас, в надежде, что все-таки вы сможете уразуметь заданный вам вопрос: что такого я должен увидеть в примерах кода, на которые вы ссылаетесь?

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

Потому «hello world» на хаскеле - это элементарный пример нечистой программы.

То есть ты согласен, что утверждение «в ФП нет никакого состояния мира» ложно?

Я согласен с тем, что чистым ФП нельзя вывести «hello world». Можно сделать функцию, которая вернет строку «hello world», но вывод строки - это уже грязная операция.

Монада позволяет очень удобно описывать свойства сразу куска кода.

Перефорс монад превращает банальнейшие операции в трах. Попробуй сделать без Debug.Trace печать значения в функциях - будешь по всей программе возить паравозы, вроде «IO ST a». С усложнением программы усугубляется и эта проблема, потому никто не может написать ни одного хотя бы среднего проекта на хаскеле, а все только сидят и рассуждают про красоту конструкций.
Я вообще плохо понимаю, кому пришло в голову описывать конвеер типом возвращаемого результата: идея конвеера хорошая - реализация ужасна. Очевидно, что кто-то очень, ну очень хотел остаться в рамках чистого ФП, в котором нет внешних свойств и состояний, а есть только тип аргументов и тип результатов.
Например, в лиспе атом (аля STM) - это тоже своего рода конвеер, но конвеер определяется просто и удобно, без необходимости жанглировать типами внутри.

Можно писать в монаде MonadError и автоматически получить механизм обработки ошибок. Или в монаде Cont и получить продолжения.

Ага, «MonadError IO Maybe a».

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

Я изменил файл - изменились результаты чтения.

Для Haskell результатом программы является функция main. В смысле, сама функция, а не результат её выполнения. А бинарник состоит из этого самого результата программы на Haskell и исполнителя монады IO (который написан не на Haskell и не является чистой функцией).

Таким образом, то что у тебя изменились результаты чтения указывает только на нечистоту исполнителя монады IO. Вот если бы от этого изменилась функция main, тогда программа на Haskell была бы нечистой.

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

package com.seriouscompany.business.java.fizzbuzz.packagenamingpackage.impl;

Проблема преувеличена, но она есть, не спорю. Конкретно жава довела классовую модель ООП до абсурда.

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

Ну и еще раз, специально для вас, в надежде, что все-таки вы сможете уразуметь заданный вам вопрос: что такого я должен увидеть в примерах кода, на которые вы ссылаетесь?

Чудовищную перегруженность и нечитаемость кода, который может быть повторно используем и расширяем. А пример был о том, насколько просты реализации перемножения матриц на Си и хаскеле, и насколько сложны и нечитаемы реализации ренжей (а не сам их вызов). Помимо стандартной библиотеки будут еще сторонние, будут еще свои собственные.
Такая ситуация не только усложняет поддержку - она тормозит еще и компиляцию, потому что стандартные библиотеки завалены миллионами строк такого кода, и его для каждого файла нужно заново читать, а анализ кода C++ тяжелый i.e. «a <b> c» - здесь неясно, что вообще записано, если не знать определения a, b, и c.

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

Для Haskell результатом программы является функция main. В смысле, сама функция, а не результат её выполнения. А бинарник состоит из этого самого результата программы на Haskell и исполнителя монады IO (который написан не на Haskell и не является чистой функцией).
Таким образом, то что у тебя изменились результаты чтения указывает только на нечистоту исполнителя монады IO. Вот если бы от этого изменилась функция main, тогда программа на Haskell была бы нечистой.

Без исполнителя IO программа не исполнится, и толку с такой программы? При всём желании сделать язык, который нельзя будет выполнять, создатели хаскеля вынуждены были смириться с осознанием того, что программы должны выполняться - иначе смысла в них нету. В итоге получается, что любая выполняющаяся программа в хаскеле становится грязной.

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

то что у тебя изменились результаты чтения указывает только на нечистоту исполнителя монады IO

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

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

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

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

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

class A {
   friend A make_A(B b);

   A(B b) {...}
private:
   ...
};

но более многословный за счет шаблонов:

template< std::size_t Cases_Count >
class prepared_select_t
	{
		template<
			mchain_props::msg_count_status_t Msg_Count_Status,
			typename... Cases >
		friend prepared_select_t< sizeof...(Cases) >
		prepare_select(
			mchain_select_params_t< Msg_Count_Status > params,
			Cases &&... cases );

		template< typename... Cases >
		prepared_select_t(
			mchain_select_params_t<
					mchain_props::msg_count_status_t::defined > params,
			Cases &&... cases );

	public :

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

А пример был о том, насколько просты реализации перемножения матриц на Си и хаскеле, и насколько сложны и нечитаемы реализации ренжей (а не сам их вызов).

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

Но, если вы уж додумались до сравнения Си с C++, то может покажите, что нужно сделать на чистом Си, чтобы иметь возможность писать код в стиле C++ных ranges?

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

Это наследие C. Но С вы почему-то противопоставляете C++.

а анализ кода C++ тяжелый i.e. «a c» - здесь неясно, что вообще записано, если не знать определения a, b, и c.

Да уж, проблема. Оказывается, чтобы анализировать код программ, нужно знать о том, что и как там используется. Браво. Еще немного и вы придете к выводу, что для написания программ еще и думать нужно. Думать!

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

Вот это и есть причина отсутствия ФП в массовом программировании. Написать компилятор, который map/filter/fold сообразит превратить в один цикл гораздо сложнее, чем таблицу виртуальных функций для ООП.

Не надо его в один цикл превращать. Иначе смысла в нём нету. И да, не сложнее.

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

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

What?

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

Software Transactional Memory

Никто не мешает её использовать в других языках от Си до Джавы.

Используют в продакшене, но не на хаскеле?! На хаскеле спокойно, ибо сложно напортачить самому с откатами, но на cи или яве? Это каким фанатом надо быть одновременно последних языков и самого STM?

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

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

Ну чем проще?

Процедурно (на Паскале):

procedure quickSort(var X: itemArray; n: integer);
type
  p_node = ^node;
  node = record
           node: integer;
           next: p_node
         end;
var
  l,r,i,j: integer;
  stack: p_node;
  temp: item;

  procedure push(i: integer);
  var
    temp: p_node;
  begin
    new(temp);
    temp^.node:=i;
    temp^.next:=stack;
    stack:=temp
  end;

  function pop: integer;
  var
    temp: p_node;
  begin
    if stack=nil then
      pop:=0
    else
    begin
      temp:=stack;
      pop:=stack^.node;
      stack:=stack^.next;
      dispose(temp)
    end
  end;

begin
  stack:=nil;
  push(n-1);
  push(0);
  repeat
    l:=pop;
    r:=pop;
    if r-l=1 then
    begin
      if compare(X[l],X[r]) then
        change(X[l],X[r])
    end
    else
    begin
      temp:=x[l + (r-l) div 2]; {random(r-l+1)+l}
      i:=l;
      j:=r;
      repeat
        while compare(temp,X[i]) do i:=i+1;
        while compare(X[j],temp) do j:=j-1;
        if i<=j then
        begin
          change(X[i],X[j]);
          i:=i+1;
          j:=j-1
        end;
      until i>j;
      if l<j then
      begin
        push(j);
        push(l)
      end;
      if i<r then
      begin
        push(r);
        push(i)
      end
    end;
  until stack=nil
end;

Haskell (честный алгоритм на массивах):

quickSort a = subSort (bounds a) a

subSort (n, m) a =
  if n >= m 
    then a
    else subSort (n, p) $ subSort (p+1, m) a1
  where (p, a1) = partition (n, m) (a ! div (n+m) 2)  a

partition (l, r) p a 
  | l >= r = (l, a)
  | a ! l < p = partition (l+1, r) p a
  | a ! r > p = partition (l, r-1) p a
  | otherwise = partition (l+1, r-1) p $ a // [(l, a ! r), (r, a ! l)]

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

Без исполнителя IO программа не исполнится, и толку с такой программы?

Эта программа может вернуть код для исполнителя IO.

Также как есть толк от языка шаблонов и constexpr Си++ и макросов Си. Они являются чистыми функциями и тоже позволяют в результате получать полезные программы.

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

Так и объектно-ориентрованный — очень сильное ограничение.

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

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

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

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

Я не знаток всяких хаскелей, если там позволено использовать побочные эффекты, то ещё куда ни шло

В любом языке общего назначения позволено использовать побочные эффекты. В Haskell считается, что программа на хаскеле в результате выдает программу для императивного исполнителя. В Clean есть тип, отображающий реальный мир. И есть много языков, которые являются функциональными, но не являются чистыми (APL, Erlang, ...).

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

Нет, не тролль. Мне правда интересно. Спасибо огромное, что участвуете в обсуждении и делитесь опытом и знаниями! В IT/CS куча евангелистов, маркетингового буллшита и т.п. Иногда очень сложно разобраться в тонкостях различных технологий, не наевшись говна и потратив кучу времени и сил впустую или на то, чем бы тебе в конечном итоге не хотелось бы заниматься... Впрочем, о чем это я?) Пишу-то я все равно на жабе, на работе, но вроде наметился вектор для того, чтобы поменять ситуацию. Давно были интересны функциональные языки и все не хватало времени нормально взяться за них и/или за какой-либо конкретно. Решил посмотреть в сторону языков для JVM: Clojure, Kotlin, Groovy, т.к. у них вроде бы неплохая интеграция с самой джавой.

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

Процедурно (на Паскале):

Откуда ты такую сортировку выдрал?

Вот реализация в последнем FPC:
https://pastebin.com/UcC1H0ux
FPC 3.0.4:
https://pastebin.com/JWRRsHzf
Чуть побольше оптимизированная в делфи:
https://pastebin.com/a8kkcgGR
На обобщениях те же алгоритмы, только объявления массива и сравнивателя отличаются.

Haskell (честный алгоритм на массивах)

Что это? Где обмен элементов? Ты какой-то странный огрызок показываешь. Вот обмен элементов:
https://pastebin.com/Sq8jWaDv
Взято из
https://koerbitz.me/posts/Efficient-Quicksort-in-Haskell.html

Как видишь, сложность алгоритмов сопоставима.

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

Нет, не тролль...

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

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

Что это? Где обмен элементов? Ты какой-то странный огрызок показываешь.

Обмен элементов вот:

  | otherwise = partition (l+1, r-1) p $ a // [(l, a ! r), (r, a ! l)]

Конкретно операция //.

Вот обмен элементов:

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

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

Да неужели?) И где же проще с ООП стало?

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

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

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

«The goal of SObjectizer is significant simplification of development of concurrent and multithreaded applications in C++. SObjectizer allows the creation of a concurrent app as a set of agent-objects which interact with each other through asynchronous messages.»
Ты уверен, что хочешь услышать мое мнение о перспективах подобного проекта и про альтернативные реализации, которые уже давно и много раз были сделаны для подобных моделей?

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

Эта проблема хорошо видна при обучении, когда человек приходит свежий, с незасранными мозгами - он может понять, что делает «b = a + 2», что делает print(«asd»), но в упор не может понять, какое действие выполняет

template <template< std::size_t Cases_Count >
class prepared_select_t
	{
		template<
			mchain_props::msg_count_status_t Msg_Count_Status,
			typename... Cases >[br]
		friend prepared_select_t< sizeof...(Cases) > ...}
Но преподы и авторы книжек ему втирают, что это правильно, что так и нужно. Я же, с моим багажом опыта, могу смело ссать в лицо этим авторам и преподавателям, потому что я знаю, что никакой функции эти строки не выполняют и программы прекрасно пишутся без них - вокруг реально выполняемых действий, а не вокруг абстрактных идей.

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

Никогда не писать на C++.

Сравнить тупую реализацию перемножения матриц в лоб на Си с реализацией библиотеки ranges – это нужно суметь.

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

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

Это наследие C. Но С вы почему-то противопоставляете C++.

Я много ругаю Си. Просто C++ я ругаю больше, поскольку он впитал все недостатки Си, добавив сверху новых.

а анализ кода C++ тяжелый i.e. «a c» - здесь неясно, что вообще записано, если не знать определения a, b, и c.

Да уж, проблема. Оказывается, чтобы анализировать код программ, нужно знать о том, что и как там используется. Браво. Еще немного и вы придете к выводу, что для написания программ еще и думать нужно.

Выраженная проблема C++, которую он развил из Си, заключается в том, что фундаментально разные конструкции языка имеют одинаковый синтаксис. «a < b > c» может значить сравнение, а может значить шаблон - это совершенно разные вещи, но анализатор кода не может определить, что имеет место на самом деле. Подобная проблема наблюдается с инициализаторами-объявлениями функций-вызовами функций.
Помимо ухудшения читаемости это приводит к более тонкой проблеме, которую я уже упоминул - принципиально невозможно сделать быстрый парсер для C++. Кодеры плачут, колются, но продолжают жрать кактус.

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

Спец либы вполне себе параллелят, но происходит это за пределами питона, а не внутри него.

Я и говорю, без костылей не поедет

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

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

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

What?

С подключением. Лямбды в C++ - это скрытый конструктор анонимного объекта, который, к тому же, не дотягивает до звания реализации такой фичи как «замыкание», которая есть в Rust. Замыкания-лямбды есть в расте, их не было в самых первых версиях, где были исключительно лямбды-вложенные функции, но замыкания неприятно отдалены от других констуркций языка - это уже костыль, которым подперли лямбды, когда увидели серьезную ограниченность онных, вызванную строго проверкой областей видимости.

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

Используют в продакшене, но не на хаскеле?! На хаскеле спокойно, ибо сложно напортачить самому с откатами, но на cи или яве? Это каким фанатом надо быть одновременно последних языков и самого STM?

STM в хаскеле используется не от хорошей жизни. Алгоритмы на блокировках, как и lock-free нетранзакционные алгоритмы при значительных трениях обыгрывают STM, а при сильных трениях уделывают его на порядки, потому что производительность STM в этой области падает экспоненциально. Проблема хаскеля в том, что lock-free ты сам не можешь писать вовсе, а алгоритмы на блокировках (MVar) часто приводят к дедлокам - чаще, чем в императивке, потому что порядок выполнения программы на хаскеле трудно угадать.

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

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

Эта программа может вернуть код для исполнителя IO.

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

Также как есть толк от языка шаблонов и constexpr Си++ и макросов Си. Они являются чистыми функциями и тоже позволяют в результате получать полезные программы.

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

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

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

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

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