// Copyright (c) 2025 GeWuYou // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. namespace GFramework.Core.functional.pipe; /// /// 提供函数式编程中的管道和组合操作扩展方法 /// public static class PipeExtensions { /// /// Pipe:把值送进函数(value.Pipe(func)) /// /// 输入值的类型 /// 函数返回结果的类型 /// 要传递给函数的输入值 /// 接收输入值并返回结果的函数 /// 函数执行后的结果 public static TResult Pipe( this TSource value, Func func) => func(value); /// /// Compose:函数组合(f1.Then(f2)) /// /// 第一个函数的输入类型 /// 第一个函数的输出类型,也是第二个函数的输入类型 /// 第二个函数的输出类型 /// 第一个要执行的函数 /// 第二个要执行的函数 /// 组合后的新函数,先执行first再执行second public static Func Then( this Func first, Func second) => x => second(first(x)); /// /// Compose:反向组合(f2.After(f1)) /// /// 第一个函数的输入类型 /// 第一个函数的输出类型,也是第二个函数的输入类型 /// 第二个函数的输出类型 /// 第二个要执行的函数 /// 第一个要执行的函数 /// 组合后的新函数,先执行first再执行second public static Func After( this Func second, Func first) => x => second(first(x)); /// /// Tap:执行副作用操作但返回原值(用于调试、日志等) /// /// 输入值的类型 /// 要执行操作的输入值 /// 要执行的副作用操作 /// 原始输入值 public static TSource Tap( this TSource value, Action action) { action(value); return value; } /// /// Map:对集合中的每个元素应用函数 /// /// 源集合元素的类型 /// 映射后集合元素的类型 /// 要映射的源集合 /// 用于转换元素的函数 /// 映射后的元素序列 public static IEnumerable Map( this IEnumerable source, Func selector) => source.Select(selector); /// /// Filter:过滤集合 /// /// 集合元素的类型 /// 要过滤的源集合 /// 用于确定是否包含元素的条件函数 /// 满足条件的元素序列 public static IEnumerable Filter( this IEnumerable source, Func predicate) => source.Where(predicate); /// /// Reduce:将集合归约为单个值 /// /// 集合元素的类型 /// 归约结果的类型 /// 要归约的源集合 /// 初始累加值 /// 累加器函数 /// 归约后的最终值 public static TResult Reduce( this IEnumerable source, TResult seed, Func accumulator) => source.Aggregate(seed, accumulator); /// /// Apply:将函数应用于值(柯里化辅助) /// /// 输入值的类型 /// 函数返回结果的类型 /// 要应用的函数 /// 要传递给函数的输入值 /// 函数执行后的结果 public static TResult Apply( this Func func, TSource value) => func(value); /// /// Curry:将二参数函数转换为柯里化形式 /// /// 第一个参数的类型 /// 第二个参数的类型 /// 函数返回结果的类型 /// 要柯里化的二参数函数 /// 柯里化后的函数,接受一个参数并返回另一个函数 public static Func> Curry( this Func func) => x => y => func(x, y); /// /// Uncurry:将柯里化函数转换回二参数函数 /// /// 第一个参数的类型 /// 第二个参数的类型 /// 函数返回结果的类型 /// 要取消柯里化的函数 /// 恢复为二参数的函数 public static Func Uncurry( this Func> func) => (x, y) => func(x)(y); /// /// Partial:部分应用函数(固定第一个参数) /// /// 第一个参数的类型 /// 第二个参数的类型 /// 函数返回结果的类型 /// 要部分应用的二参数函数 /// 要固定的第一个参数值 /// 部分应用后的函数,只接受第二个参数 public static Func Partial( this Func func, T1 firstArg) => x => func(firstArg, x); /// /// Match:模式匹配(类似switch表达式) /// /// 输入值的类型 /// 匹配结果的类型 /// 要进行模式匹配的输入值 /// 匹配案例数组,每个包含谓词和处理器 /// 匹配到的处理结果 /// 当没有匹配的案例时抛出 public static TResult Match( this TSource value, params (Func predicate, Func handler)[] cases) { foreach (var (predicate, handler) in cases) { if (predicate(value)) return handler(value); } throw new InvalidOperationException("No matching case found"); } /// /// MatchOrDefault:带默认值的模式匹配 /// /// 输入值的类型 /// 匹配结果的类型 /// 要进行模式匹配的输入值 /// 当没有匹配案例时的默认返回值 /// 匹配案例数组,每个包含谓词和处理器 /// 匹配到的处理结果或默认值 public static TResult MatchOrDefault( this TSource value, TResult defaultValue, params (Func predicate, Func handler)[] cases) { foreach (var (predicate, handler) in cases) { if (predicate(value)) return handler(value); } return defaultValue; } /// /// If:条件执行 /// /// 输入值的类型 /// 要进行条件判断的输入值 /// 条件判断函数 /// 条件为真时执行的转换函数 /// 条件为真时返回转换后的值,否则返回原值 public static TSource If( this TSource value, Func predicate, Func thenFunc) => predicate(value) ? thenFunc(value) : value; /// /// IfElse:条件分支 /// /// 输入值的类型 /// 要进行条件判断的输入值 /// 条件判断函数 /// 条件为真时执行的转换函数 /// 条件为假时执行的转换函数 /// 根据条件返回相应的转换结果 public static TSource IfElse( this TSource value, Func predicate, Func thenFunc, Func elseFunc) => predicate(value) ? thenFunc(value) : elseFunc(value); /// /// As:类型转换(安全转换) /// /// 源类型的泛型参数 /// 目标类型的泛型参数 /// 要进行类型转换的值 /// 转换后的值,如果转换失败则返回null public static TResult? As( this TSource value) where TResult : class => value as TResult; /// /// Cast:强制类型转换 /// /// 目标类型的泛型参数 /// 要进行类型转换的对象 /// 强制转换后的值 public static TResult Cast( this object value) => (TResult)value; /// /// Also:执行操作并返回原值 /// /// 输入值的类型 /// 要执行操作的输入值 /// 要执行的操作 /// 原始输入值 public static TSource Also( this TSource value, Action action) { action(value); return value; } /// /// Let:将值转换为另一个值 /// /// 输入值的类型 /// 转换结果的类型 /// 要进行转换的输入值 /// 用于转换值的函数 /// 转换后的结果 public static TResult Let( this TSource value, Func transform) => transform(value); /// /// TakeIf:条件返回值或null /// /// 输入值的类型 /// 要进行条件判断的输入值 /// 条件判断函数 /// 条件为真时返回原值,否则返回null public static TSource? TakeIf( this TSource value, Func predicate) where TSource : class => predicate(value) ? value : null; /// /// TakeUnless:条件相反的TakeIf /// /// 输入值的类型 /// 要进行条件判断的输入值 /// 条件判断函数 /// 条件为假时返回原值,否则返回null public static TSource? TakeUnless( this TSource value, Func predicate) where TSource : class => !predicate(value) ? value : null; /// /// Repeat:重复执行函数n次 /// /// 输入值的类型 /// 初始输入值 /// 重复执行的次数 /// 要重复执行的函数 /// 经过多次变换后的最终值 public static TSource Repeat( this TSource value, int times, Func func) { var result = value; for (int i = 0; i < times; i++) { result = func(result); } return result; } /// /// Try:安全执行,捕获异常 /// /// 输入值的类型 /// 函数返回结果的类型 /// 要传递给函数的输入值 /// 要安全执行的函数 /// 包含执行状态、结果和错误信息的元组 public static (bool success, TResult? result, Exception? error) Try( this TSource value, Func func) { try { return (true, func(value), null); } catch (Exception ex) { return (false, default, ex); } } /// /// Memoize:缓存函数结果 /// /// 函数输入参数的类型 /// 函数返回结果的类型 /// 要缓存结果的函数 /// 带有缓存功能的包装函数 public static Func Memoize( this Func func) where TSource : notnull { var cache = new Dictionary(); return x => { if (cache.TryGetValue(x, out var result)) return result; result = func(x); cache[x] = result; return result; }; } }