当前位置: 首页 > article >正文

名词(术语)了解--柯里化(Currying)

名词(术语)了解–柯里化(Currying)

在这里插入图片描述

柯里化的定义

柯里化是一种将接受多个参数的函数转换成一系列使用单个参数的函数的技术。

这个概念是以逻辑学家 Haskell Curry 命名的。

让我们通过一个简单的例子来说明:

  1. 普通函数:
function add(x, y, z) {
    return x + y + z;
}
console.log(add(1, 2, 3)); // 输出: 6
  1. 柯里化后的函数:
function curriedAdd(x) {
    return function(y) {
        return function(z) {
            return x + y + z;
        }
    }
}
console.log(curriedAdd(1)(2)(3)); // 输出: 6

柯里化的优点

  1. 参数复用
const addTen = curriedAdd(10);
console.log(addTen(2)(3)); // 15
console.log(addTen(5)(7)); // 22
  1. 延迟执行:可以等到收集完所有参数后再执行。

  2. 函数组合:更容易实现函数组合。

实现通用的柯里化函数

下面是一个通用的柯里化函数实现:

function curry(fn) {
    return function curried(...args) {
        if (args.length >= fn.length) {
            return fn.apply(this, args);
        }
        return function(...moreArgs) {
            return curried.apply(this, args.concat(moreArgs));
        }
    };
}

// 使用示例
function sum(a, b, c) {
    return a + b + c;
}

const curriedSum = curry(sum);
console.log(curriedSum(1)(2)(3));     // 6
console.log(curriedSum(1, 2)(3));     // 6
console.log(curriedSum(1)(2, 3));     // 6

实际应用场景

  1. 事件处理
const handleChange = curry((name, event) => {
    console.log(name, event.target.value);
});

// 可以预设参数
const handleUserNameChange = handleChange('username');
input.addEventListener('change', handleUserNameChange);
  1. 数据处理
const map = curry((fn, arr) => arr.map(fn));
const multiply = curry((x, y) => x * y);

const multiplyBy2 = map(multiply(2));
console.log(multiplyBy2([1, 2, 3])); // [2, 4, 6]
  1. 配置函数
const ajax = curry((url, method, data) => {
    // 发送请求
});

const getFromAPI = ajax('api.example.com');
const getUser = getFromAPI('GET');
const postUser = getFromAPI('POST');

// 使用
getUser({id: 1});
postUser({name: 'John'});

扩展:

实际示例

基础示例

// 普通函数调用
add(1, 2, 3);  // 6

// 柯里化函数调用
curriedAdd(1)(2)(3);  // 6

// 也可以分步调用
const add1 = curriedAdd(1);
const add1and2 = add1(2);
const result = add1and2(3);  // 6

实用示例

// 日志记录器
const log = (type) => (message) => {
    console.log(`[${type}] ${message}`);
}

const errorLog = log('ERROR');
const infoLog = log('INFO');

errorLog('发生错误');  // [ERROR] 发生错误
infoLog('普通信息');   // [INFO] 普通信息

柯里化的优势

  1. 参数复用

    • 可以固定部分参数,创建新的函数
    • 减少重复代码
  2. 延迟执行

    • 不需要立即给出所有参数
    • 可以等到真正需要时再传入剩余参数
  3. 函数组合

    • 更容易实现函数组合
    • 提高代码的模块化程度

通用柯里化函数实现

function curry(fn) {
    return function curried(...args) {
        // 如果传入的参数个数大于等于原函数的参数个数,直接调用原函数
        if (args.length >= fn.length) {
            return fn.apply(this, args);
        }
        
        // 否则返回一个新函数,等待接收剩余参数
        return function(...args2) {
            return curried.apply(this, args.concat(args2));
        }
    };
}

// 使用示例
function add(x, y, z) {
    return x + y + z;
}

const curriedAdd = curry(add);
console.log(curriedAdd(1)(2)(3));  // 6
console.log(curriedAdd(1, 2)(3));  // 6
console.log(curriedAdd(1)(2, 3));  // 6

实际应用场景

事件处理

const handleChange = (fieldName) => (event) => {
    setState({
        [fieldName]: event.target.value
    });
}

// 使用
<input onChange={handleChange('username')} />
<input onChange={handleChange('password')} />

数据处理

const filter = (predicate) => (array) => array.filter(predicate);
const isEven = n => n % 2 === 0;

const filterEven = filter(isEven);
console.log(filterEven([1, 2, 3, 4]));  // [2, 4]

注意事项

  1. 性能考虑:柯里化会创建多个闭包,可能会带来轻微的性能开销。

  2. 代码可读性:过度使用柯里化可能会降低代码的可读性。

  3. 调试难度:柯里化的函数可能会使调试变得更复杂。

最佳实践

  1. 在适当的场景使用柯里化

    • 参数复用频繁的场景
    • 需要延迟执行的场景
    • 函数组合的场景
  2. 保持函数的纯度

    • 避免在柯里化函数中使用副作用
    • 保持函数的可预测性

http://www.kler.cn/news/366676.html

相关文章:

  • Android调用系统相机录像并设置参数
  • Midjourney上线图像编辑,他们终于知道什么叫开放了。
  • AJAX—— jQuery 发送 AJAX 请求
  • 8.three.js相机详解
  • AnaTraf | 全面掌握网络健康状态:全流量的分布式网络性能监测系统
  • 如何接受Date范围的数据
  • spark读取parquet文件
  • 常见的音视频格式介绍
  • Cilium + ebpf 系列文章- (七)Cilium-LoadBalancer类型的SVC的IPPool
  • 总裁主题CeoMax-Pro主题7.6开心版
  • 在linux系统中查看具体文件大小命令
  • 【C++习题】12.滑动窗口_将 x 减到 0 的最小操作数
  • 通过Docker Compose构建自己的Java项目
  • 【升华】另一个神经网络学习框架pytorch
  • 智能台灯设计(一)原理图设计
  • 大话网络协议:从OSI七层模型说开去
  • Git的原理和使用(六)
  • android 生成json 文件
  • row_number() over (partition by 分组列 order by 排序列 desc)、row_number() 函数、分组排序函数
  • 计算机网络(十二) —— 高级IO
  • 12_Linux进程管理命令详解
  • python如何通过json以及pickle读写保存数据
  • gin入门教程(9):路由分组与路由版本控制
  • MySQL 存储结构
  • 基于信号分解和多种深度学习结合的上证指数预测模型
  • 基于Multisim的音频放大电路设计与仿真