Информация об изменениях

Сообщение Re[14]: Try из библиотеки LanguageExt.Core от 19.01.2022 5:23

Изменено 19.01.2022 5:31 Sinclair

Re[14]: Try из библиотеки LanguageExt.Core
Здравствуйте, vaa, Вы писали:
S>>Нет конечно, ничего не работает. WriteLine("DONE") не выполняется; аргумент Fail при исключении тоже не выполнится:
S>>
S>>Try((int x) => { WriteLine("DONE"); throw new InvalidOperationException(); return x; }).Match(_ => WriteLine("OK"), exn => WriteLine(exn));
S>>

vaa>И откуда возьмется x чтобы лямбда посчиталась? результат работы try функция а не ее результат. хм... матч то тут причем?
Всё верно.
Чего мы ожидаем от конструкции Try().Match()?
Что она превратит некую функцию, бросающую исключения, в функцию, которая исключений не бросает, а выполняет действия, указанные в match.
Результатом указанного кода должна стать Action<int>, которая при вызове на любом аргументе выводит "InvalidOperationException".
А в реальности результатом будет Unit. Увы.

Я вижу, вам сложно воспринимать код C#.
Давайте я напишу помедленнее.
Начнём с двух простых методов.
Func<int, int> foo = x => x % 2 == 0 ? 1 : throw new Exception("Oops");
Func<int> bar = () => foo(DateTime.Now.Millisecond);

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

Давайте теперь попробуем посмотреть, что можно с ними сделать с помощью Try.
Начнём со второго:
// 1. Working with the parameterless function:
// 1.1. Wrapping into the Try monad:
var tryBar = Try(bar);
// 1.2 Direct execution (note the lack of params in Try):
var barResult = tryBar.Try(); // Result<int>
// 1.3. Coalescing exceptions into default value
var barFinalResult = barResult.Match(x => x, ex => 1);
Assert.Equal(1, barFinalResult);
// 1.4. Shortcut coalescing:
barFinalResult = tryBar.Match(x => x, ex => 1);
Assert.Equal(1, barFinalResult);
// 1.5. Returnless matching:
tryBar.Match(x => WriteLine(x), ex => WriteLine(ex));

удобная вроде штука — мы превратили Func<int> throws Exception сначала в Func<Result<int>>, затем просто в Result<int>, а потом и в просто int.
Ну, или если нам результат функции нужен был просто в рамках некоего побочного эффекта (вывод на экран), то мы это сделали в одну строку в 1.5.


Попробуем сделать что-то похожее с foo:
var tryFoo = Try(foo);

Логично ожидать аналогичного поведения — наверное, у tryFoo будет доступен метод Try(int), который тоже вернёт Result<int>, чтобы по нему можно было матчиться.
А методы Match должны либо принимать int в качестве дополнительного параметра.
Ну, то есть мне логичным видится делать даже не это, а строить обратно Func<int, int> либо Action<int>, в зависимости от сигнатур переданных в Match обработчиков.
Но это бы означало ленивость Match, что противоречит поведению того убогого Match, который реализован в этой библиотеке для функций в стиле bar.

Но нет! у tryFoo есть только один метод Try, у которого нет параметров. И возвращает он вовсе не Result<int>, а Result<Func<int, int>>, который полностью бесполезен для наших целей.
Мы, конечно, можем выковырять этот Func<int, int> из Result, но даже после Match он продолжает сыпать исключениями.
Никаким способом мы из tryFoo не можем получить ожидаемое — Func<int, int>, которая для любого аргумента вернёт 1.
Поэтому здравомыслие автора библиотеки вызывает вопросы.

Если что-то непонятно, спрашивайте.
Re[14]: Try из библиотеки LanguageExt.Core
Здравствуйте, vaa, Вы писали:
S>>Нет конечно, ничего не работает. WriteLine("DONE") не выполняется; аргумент Fail при исключении тоже не выполнится:
S>>
S>>Try((int x) => { WriteLine("DONE"); throw new InvalidOperationException(); return x; }).Match(_ => WriteLine("OK"), exn => WriteLine(exn));
S>>

vaa>И откуда возьмется x чтобы лямбда посчиталась? результат работы try функция а не ее результат. хм... матч то тут причем?
Всё верно.
Чего мы ожидаем от конструкции Try().Match()?
Что она превратит некую функцию, бросающую исключения, в функцию, которая исключений не бросает, а выполняет действия, указанные в match.
Результатом указанного кода должна стать Action<int>, которая при вызове на любом аргументе выводит "InvalidOperationException".
А в реальности результатом будет Unit. Увы.

Я вижу, вам сложно воспринимать код C#.
Давайте я напишу помедленнее.
Начнём с двух простых методов.
Func<int, int> foo = x => x % 2 == 0 ? 1 : throw new Exception("Oops");
Func<int> bar = () => foo(DateTime.Now.Millisecond);

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

Давайте теперь попробуем посмотреть, что можно с ними сделать с помощью Try.
Начнём со второго:
// 1. Working with the parameterless function:
// 1.1. Wrapping into the Try monad:
var tryBar = Try(bar);
// 1.2 Direct execution (note the lack of params in Try):
var barResult = tryBar.Try(); // Result<int>
// 1.3. Coalescing exceptions into default value
var barFinalResult = barResult.Match(x => x, ex => 1);
Assert.Equal(1, barFinalResult);
// 1.4. Shortcut coalescing:
barFinalResult = tryBar.Match(x => x, ex => 1);
Assert.Equal(1, barFinalResult);
// 1.5. Returnless matching:
tryBar.Match(x => WriteLine(x), ex => WriteLine(ex));

удобная вроде штука — мы превратили Func<int> throws Exception сначала в Func<Result<int>>, затем просто в Result<int>, а потом и в просто int.
Ну, или если нам результат функции нужен был просто в рамках некоего побочного эффекта (вывод на экран), то мы это сделали в одну строку в 1.5.


Попробуем сделать что-то похожее с foo:
var tryFoo = Try(foo);

Логично ожидать аналогичного поведения — наверное, у tryFoo будет доступен метод Try(int), который тоже вернёт Result<int>, чтобы по нему можно было матчиться.
А методы Match должны принимать int в качестве дополнительного параметра.
Ну, то есть мне логичным видится делать даже не это, а строить обратно Func<int, int> либо Action<int>, в зависимости от сигнатур переданных в Match обработчиков.
Но это бы означало ленивость Match, что противоречит поведению того убогого Match, который реализован в этой библиотеке для функций в стиле bar.

Но нет! у tryFoo есть только один метод Try, у которого нет параметров. И возвращает он вовсе не Result<int>, а Result<Func<int, int>>, который полностью бесполезен для наших целей.
Мы, конечно, можем выковырять этот Func<int, int> из Result, но даже после Match он продолжает сыпать исключениями.
Никаким способом мы из tryFoo не можем получить ожидаемое — Func<int, int>, которая для любого аргумента вернёт 1.
Поэтому здравомыслие автора библиотеки вызывает вопросы.

Если что-то непонятно, спрашивайте.