// 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 GFramework.Core.functional.types;
namespace GFramework.Core.functional.functions;
///
/// 函数式编程扩展方法集合,提供柯里化、偏函数应用、重复执行、安全执行和缓存等功能
///
public static class FunctionExtensions
{
///
/// 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);
///
/// 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;
}
///
/// 尝试执行一个转换函数,并将结果包装在Result对象中,捕获可能发生的异常
///
/// 输入值的类型
/// 转换函数返回值的类型
/// 要进行转换操作的源值
/// 用于转换源值的函数委托
/// 如果转换成功则返回包含结果的成功状态,如果发生异常则返回包含异常信息的失败状态
public static Result TryResult(
this TSource value,
Func func)
{
// 执行转换函数并处理可能的异常
try
{
return Result.Success(func(value));
}
catch (Exception ex)
{
return Result.Failure(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;
};
}
///
/// Map:对单个对象应用函数
///
/// 源对象类型
/// 映射后的类型
/// 要映射的源对象
/// 转换函数
/// 映射后的对象
public static TResult Map(
this TSource source,
Func selector)
=> selector(source);
}