Files
SjkScripts/Functional/OptionExtensions.cs
ronnie 99606ce358
All checks were successful
Build NuGet / build (push) Successful in 44s
Added First or None to IOption
2026-04-06 13:57:08 -04:00

100 lines
3.5 KiB
C#

using System.Diagnostics;
namespace SJK.Functional;
public static class OptionExtensions
{
public static IEnumerable<TResult> Match<T, TResult>(this IEnumerable<IOption<T>> values, Func<T, TResult> onSome, Func<TResult> onNone)
{
foreach (var item in values)
{
yield return item.Match(onSome, onNone);
}
}
// public static IOption<T> GetValue<Tkey, T>(this IDictionary<Tkey, T> value, Tkey key) where Tkey : notnull
// {
// if (value.TryGetValue(key, out var v))
// {
// return v.ToOption();
// }
// return None<T>.Of();
// }
public static IOption<T> GetValue<Tkey, T>(this IReadOnlyDictionary<Tkey, T> value, Tkey key) where Tkey : notnull
{
if (value.TryGetValue(key, out var v))
{
return v.ToOption();
}
return None<T>.Of();
}
public static IOption<T> OrElse<T>(this IOption<T> option, Func<IOption<T>> fallback)
{
return option.Match(
some => option,
() => fallback()
);
}
public static IOption<TResult> BindUsing<TDisposable, TResult>(
this IOption<TDisposable> option,
Func<TDisposable, IOption<TResult>> func)
where TDisposable : IDisposable
{
return option.Match(
some =>
{
using (some) return func(some);
},
() => None<TResult>.Of()
);
}
public static IOption<T> ToOption<T>(this T? value) => value != null ? Some<T>.Of(value) : None<T>.Of();
[StackTraceHidden]
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T OrThrow<T, TEx>(this IOption<T> option, Func<TEx> exceptionFactory) where TEx : Exception
{
if (option.HasValue(out var value))
return value;
throw exceptionFactory();
}
public static IEither<L, R> ToEither<Tvalue, L, R>(this Tvalue value, Func<Tvalue, bool> isSuccess, Func<R> ok, Func<Tvalue, L> err)
{
return isSuccess(value) ? new Right<L, R>(ok()) : new Left<L, R>(err(value));
}
public static IEither<L, R> ToEither<Tvalue, L, R>(this Tvalue value, Tvalue successValue, Func<R> ok, Func<Tvalue, L> err) where Tvalue : notnull
{
return value.ToEither(e => e.Equals(successValue), ok, err);
}
// public static IEnumerable<IOption<T>> ToOptions<T>(this IEnumerable<T> value) => value.Select(thing => thing.ToOption());
public static Some<T> ToSome<T>(this T value) where T : notnull => Some<T>.Of(value);
public static void IfSome<T>(this IOption<T> value, Action<T> onSome) => value.Match(onSome, () => { });
public static void IfNone<T>(this IOption<T> value, Action onNone) => value.Match(_ => { }, onNone);
public static T Or<T>(this IOption<T> value, Func<T> @default) => value.Or(@default());
public static IEnumerable<T> OnlySomes<T>(this IEnumerable<IOption<T>> options)
{
foreach (var item in options)
{
if (item.HasValue(out var item2))
yield return item2;
}
}
// public static None<T> ToNone<T>(this T value) => None<T>.Of();
public static Option<T> ToStructOption<T>(this IOption<T> option) => option.HasValue(out var value) ? Option<T>.Some(value) : Option<T>.None;
public static IOption<T> ToClassOption<T>(this Option<T> option) => option.HasValue ? option.Value.ToOption() : None<T>.Of();
public static IOption<T> FirstOrNone<T>(this IEnumerable<T> options) => options.Any() ? options.First().ToOption() : None<T>.Of();
public static IOption<T> FirstOrNone<T>(this IEnumerable<T> options, Predicate<T> predicate)
{
foreach (var item in options)
{
if (predicate(item))
{
return item.ToOption();
}
}
return None<T>.Of();
}
}