Необходимости менять не было, но желание было.
Например, было желание переехать с NLog на Serilog. И, кстати, переехали в итоге.
Правда в абстракции для логгера я тоже не вижу смысла, как для IoC контейнера.
Переехать с одного логгера на другой оказалось несложно без всяких абстракций.
Я бы не был так категоричен.
Во первых, получение зависимостей через DI не означает обязательное использование IoC-контейнера.
У ручной инициализации есть свои преимущества.
Во вторых, даже при использовании IoC-контейнера, я бы всё равно не стал отказываться от проверок параметров конструктора. По-хорошему класс ничего не должен знать о том как он инициализируется. Вы всегда можете захотеть инициализировать его вручную.
Насколько я понимаю, LINQ состоит из нескольких частей:
1. SQL-подобный синтаксис, который просто транслируется в вызовы определённых методов и ничего про их ленивость не знает.
2. Возможность в C#, которая позволяет транслировать лямбда выражения в деревья выражений. Тоже никакого отношения к ленивости не имеет.
3. Набор методов расширений из пространств имён System.Linq, System.Xml.Linq и System.Data.Linq. Часть из которых ленивые, а часть из которых нет(Sum, All, Min, Max, и т.д.)
Так что я не могу согласиться с тем, что «на этом(ленивость) весь Linq построен».
Но даже если бы это было так, LINQ это только часть C#. И как раз LINQ — это кусочек функционального программирования в C#. Я слышал, что его даже хотели назвать LINM(Language Integrated Monads), но решили, что будет понятнее Queries.
Впрочем, ленивость — это, наверное, самая незначительная вещь для ФП.
Разверну мысль.
Для функционального программирования очень важно чтобы функции не имели видимых побочных эффектов. Например в Haskell все функции по умолчанию чистые. Очевидно, что в C# это не так.
И мне интересно можно ли как-то пойти обратным путём и как-то контролировать побочные эффекты функций.
Например, есть System.Diagnostics.Contracts.PureAttribute и JetBrains.Annotations.PureAttribute, но, насколько я понимаю, они не контролируют побочные эффекты метода.
Есть даже пропозал C# Pure Function Keyword to Mark No Side Effects Or External Dependencies, но пока, увы, только на рассмотрении.
А какой популярный язык не является «почти функциональным»?
Автор выделил 3 критерия, которым должен соответствовать язык, чтобы называться функциональным(хотя я с ними не согласен, но допустим):
Иметь функции высшего порядка
Неизменяемость(иммутабельность) по умолчанию
Автоматическое управление памятью
C# не соответствует пункту №2, т.е. у него есть только функции высшего порядка и сборка мусора.
Навскидку функции высшего порядка и сборка мусора есть в D, Python, JavaScript, Java, PHP, Ruby, Swift и Go.
Сюда ещё можно отнести C++, так как хоть у него и нет сборки мусора, но есть умные указатели и функции высшего порядка.
Да, я хочу что-то вроде этого, но только чтобы не надо было добавлять новый метод-расширение, когда у меня появляется метод с другим числом параметров.
В принципе, конечно можно один раз сделать 100500 вариантов функции Curry один раз на все случаи жизни.
Более того, можно взять language-ext в котором это уже сделано(правда только для Func, хорошо бы ещё и для Action).
Но в общем, согласен, что это решает проблему с каррированием.
И всё? Есть ли в C# возможность каррирования, частичного применения, ленивости, контроля за сайд-эффектами?
Например, можете ли вы привести универсальный способ каррировать произвольную функцию?
Или как-то ограничить функцию чтобы она не могла иметь побочных эффектов?
Я не спорю, что на C# можно писать в функциональном стиле, но называть C# функциональным языком я бы не стал.
Это не эквивалентный код. Ваш код сразу вернёт таск, который при выполнении будет приостановлен на 10 миллисекунд, а код в посте будет сначала приостановлен на 10 миллисекунд, а затем вернёт таск.
А ещё мне кажется, что GraphQL сильно похож на OData(который, кстати, появился ещё в 2007 году).
Но я с GraphQL почти не знаком, так что могу ошибаться.
Например, было желание переехать с NLog на Serilog. И, кстати, переехали в итоге.
Правда в абстракции для логгера я тоже не вижу смысла, как для IoC контейнера.
Переехать с одного логгера на другой оказалось несложно без всяких абстракций.
Во первых, получение зависимостей через DI не означает обязательное использование IoC-контейнера.
У ручной инициализации есть свои преимущества.
Во вторых, даже при использовании IoC-контейнера, я бы всё равно не стал отказываться от проверок параметров конструктора. По-хорошему класс ничего не должен знать о том как он инициализируется. Вы всегда можете захотеть инициализировать его вручную.
Не совсем понятен вопрос. О каких сценариях идёт речь?
Не могли бы вы привести примеры таких сценариев?
1. SQL-подобный синтаксис, который просто транслируется в вызовы определённых методов и ничего про их ленивость не знает.
2. Возможность в C#, которая позволяет транслировать лямбда выражения в деревья выражений. Тоже никакого отношения к ленивости не имеет.
3. Набор методов расширений из пространств имён System.Linq, System.Xml.Linq и System.Data.Linq. Часть из которых ленивые, а часть из которых нет(Sum, All, Min, Max, и т.д.)
Так что я не могу согласиться с тем, что «на этом(ленивость) весь Linq построен».
Но даже если бы это было так, LINQ это только часть C#. И как раз LINQ — это кусочек функционального программирования в C#. Я слышал, что его даже хотели назвать LINM(Language Integrated Monads), но решили, что будет понятнее Queries.
Впрочем, ленивость — это, наверное, самая незначительная вещь для ФП.
Для функционального программирования очень важно чтобы функции не имели видимых побочных эффектов. Например в Haskell все функции по умолчанию чистые. Очевидно, что в C# это не так.
И мне интересно можно ли как-то пойти обратным путём и как-то контролировать побочные эффекты функций.
Например, есть System.Diagnostics.Contracts.PureAttribute и JetBrains.Annotations.PureAttribute, но, насколько я понимаю, они не контролируют побочные эффекты метода.
Есть даже пропозал C# Pure Function Keyword to Mark No Side Effects Or External Dependencies, но пока, увы, только на рассмотрении.
Автор выделил 3 критерия, которым должен соответствовать язык, чтобы называться функциональным(хотя я с ними не согласен, но допустим):
C# не соответствует пункту №2, т.е. у него есть только функции высшего порядка и сборка мусора.
Навскидку функции высшего порядка и сборка мусора есть в D, Python, JavaScript, Java, PHP, Ruby, Swift и Go.
Сюда ещё можно отнести C++, так как хоть у него и нет сборки мусора, но есть умные указатели и функции высшего порядка.
P.S.: А почему убрали ссылку на Functional Programming in C#? В оригинальной статье она есть.
В принципе, конечно можно один раз сделать 100500 вариантов функции Curry один раз на все случаи жизни.
Более того, можно взять language-ext в котором это уже сделано(правда только для Func, хорошо бы ещё и для Action).
Но в общем, согласен, что это решает проблему с каррированием.
Например, можете ли вы привести универсальный способ каррировать произвольную функцию?
Или как-то ограничить функцию чтобы она не могла иметь побочных эффектов?
Я не спорю, что на C# можно писать в функциональном стиле, но называть C# функциональным языком я бы не стал.
Она про async/await из C#, но, думаю, принципиальной разницы тут нет.
Но я с GraphQL почти не знаком, так что могу ошибаться.