// 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. using System.Collections.Concurrent; namespace GFramework.Core.functional.functions; /// /// 函数式编程扩展方法集合,提供柯里化、偏函数应用、重复执行、安全执行和缓存等功能 /// public static class FunctionExtensions { #region Repeat /// /// Repeat:对值重复应用函数 n 次 /// /// /// 当 times 小于 0 时抛出 /// public static T Repeat( this T value, int times, Func func) { ArgumentOutOfRangeException.ThrowIfNegative(times); var result = value; for (var i = 0; i < times; i++) result = func(result); return result; } #endregion #region Try → Result /// /// Try:安全执行并返回 language-ext 的 Result /// public static Result Try( this TSource value, Func func) { try { return new Result(func(value)); } catch (Exception ex) { return new Result(ex); } } #endregion #region Memoize (Unbounded / Unsafe) /// /// MemoizeUnbounded: /// 对函数结果进行无界缓存(线程安全) /// ⚠ 注意: /// - 缓存永不释放 /// - TSource 必须具有稳定的 Equals / GetHashCode /// - 仅适用于纯函数 /// public static Func MemoizeUnbounded( this Func func) where TSource : notnull { var cache = new ConcurrentDictionary(); return key => cache.GetOrAdd(key, func); } #endregion #region Partial (Advanced) /// /// Partial:部分应用(二参数函数固定第一个参数) /// ⚠ 偏函数应用属于高级用法,不建议在业务代码滥用 /// public static Func Partial( this Func func, T1 firstArg) { return second => func(firstArg, second); } #endregion }