// 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;
using GFramework.Core.Functional;
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
}