柯里化函数的实现

记录柯里化函数实现的学习过程:

柯里化通常也称部分求值,其含义是给函数分步传递参数,每次传递参数后部分应用参数,并返回一个更具体的函数接受剩下的参数,这中间可嵌套多层这样的接受部分参数函数,直至返回最后结果。

如果要实现下面这个方法:

add(2)(1, 3, 4)(2, 3)(3)(4, 6)(7, 98)() // 133

上面这个函数当参数为空的时候执行了内部参数所有值的相加,所以我们应该考虑当参数不为空的时候将缓存起来,在为空的时候再相加,这样的思路会用闭包的方式来实现。下面是实现方法:

function add () {
  // 用来缓存所有的arguments值
  let args = [].slice.call(arguments);
  // 新建currying函数实现柯里化
  let currying = function () {
    // 如果参数为空,那么递归停止,返回执行结果
    if (arguments.length === 0) {
      return args.reduce((a, b) => a + b);
    } else {
      // 否则将参数保存到args里面,返回currying方法
      args.push(...arguments);
      return currying
    }
  }
  return currying
}
add(2)(1, 3, 4)(2, 3)(3)(4, 6)(7, 98)() // 133

上面有需要注意的一点,因为currying函数里面使用arguments,所以currying不能使用箭头函数,箭头函数内部的arguments的用法与箭头函数内部的this差不多,它取的是上一级函数的arguments值。如果想用箭头函数,currying函数可以这样改动:

  let currying = (...rest) => {
    // 如果参数为空,那么递归停止,返回执行结果
    if (rest.length === 0) {
      return args.reduce((a, b) => a + b);
    } else {
      // 否则将参数保存到args里面,返回currying方法
      args.push(...rest);
      return currying
    }
  }

我们返回的currying函数还可以使用callee来实现,原理相同,单数严格模式下不能使用:

function add () {
  // 用来缓存所有的arguments值
  let args = [].slice.call(arguments);
  // 新建currying函数实现柯里化
  return function () {
    // 如果参数为空,那么递归停止,返回执行结果
    if (arguments.length === 0) {
      return args.reduce((a, b) => a + b);
    } else {
      // 否则将参数保存到args里面,返回currying方法
      args.push(...arguments);
      return arguments.callee
    }
  }
}
add(2)(1, 3, 4)(2, 3)(3)(4, 6)(7, 98)() // 133

对普通函数进行柯里化:

// 柯里化函数的构造方法
function curry (fn) {
  // 缓存除第一个参数的所有参数
  let args = [].slice.call(arguments, 1);
  let _fn = function () {
    if (arguments.length === 0) {
      return fn.apply(this, args)
    } else {
      args.push(...arguments);
      return _fn
    }
  }
  return _fn
}
function add () {
  return [].reduce.call(arguments, (a, b) => a + b)
}
console.log(curry(add, 2)(1, 3, 4)(2, 3)(3)(4, 6)(7, 98)()) // 133

举例柯里化函数思想实现的场景:

如减少重复传递的参数

function simpleURL(protocol, domain, path) {
    return protocol + "://" + domain + "/" + path;
}

我们使用的时候将会这样:

var myurl = simpleURL(‘http‘, ‘mysite‘, ‘home.html‘);
var myurl2 = simpleURL(‘http‘, ‘mysite‘, ‘aboutme.html‘);

我们可以用柯里化的思想改写:

function curry (fn) {
  // 缓存除第一个参数的所有参数
  let args = [].slice.call(arguments, 1);
  return function () {return fn.apply(this, args.concat(...arguments))
  }
}

// 避免每次调用重复传参
let myURL1 = curry(simpleURL, ‘https‘, ‘mysite‘);
let res1 = myURL1(‘home.html‘);    //

console.log(res1);//https://mysite/home.html

let myURL2 = curry(simpleURL, ‘http‘, ‘mysite‘);
let res2 = myURL2(‘aboutme.html‘);    //

console.log(res2);//http://mysite/aboutme.html

原文地址:https://www.cnblogs.com/kdcg/p/10192421.html

时间: 2024-08-29 23:28:12

柯里化函数的实现的相关文章

javascript中利用柯里化函数实现bind方法

柯理化函数思想:一个js预先处理的思想:利用函数执行可以形成一个不销毁的作用域的原理,把需要预先处理的内容都储存在这个不销毁的作用域中,并且返回一个小函数,以后我们执行的都是小函数,在小函数中把之前预先存储的值进行相关的操作处理即可: 柯里化函数主要起到预处理的作用: bind方法的作用:把传递进来的callback回调方法中的this预先处理为上下文context; /** * bind方法实现原理1 * @param callback [Function] 回调函数 * @param con

浅谈JavaScript中的柯里化函数

首先,不可避免的要引经据典啦,什么是柯里化函数呢(from baidu): 在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术.这个技术由 Christopher Strachey 以逻辑学家 Haskell Curry 命名的,尽管它是 Moses Schnfinkel 和 Gottlob Frege 发明的. 用于创建已经设置好了一个或多个参数的函数 与函数绑定相似,他们之间的区

Swift # 柯里化函数

前言 此次文章,讲述的是Swift的一个新特性(柯里化函数),可能很多iOS开发人员是第一次听这个词汇,包括我自己也是,自己也用了几天时间才总结出来,希望能帮助到各位咯,个人感觉偏向有开发经验的码友,如果零基础的看懂,希望能给个赞,??! 如果喜欢我的文章,可以关注我,随着后续不断学习Swift中,陆续还会有更新ing.... 什么是柯里化函数? 柯里化(Currying),又称部分求值(Partial Evaluation),是一种函数式编程思想,就是把接受多个参数的函数转换成接收一个单一参数

JavaScript的柯里化函数

柯里化,或者说部分应用,是一种函数式编程的技术,对于熟悉以传统方式编写 JavaScript 代码的人来说可能会很费解.但如果使用得当,它可以使你的 JavaScript 函数更具可读性. 更具可读性和灵活性 函数式 JavaScript 被吹捧的优点之一就是拥有短小紧凑的代码风格,可以用最少行数.更少重复的代码得到正确的结果.有时这会以牺牲可读性为代价:如果你还不熟悉函数式编程的方法,这种方法写的代码会很难阅读和理解. 如果之前你遇到过柯里化这个术语,但是不知道它是什么意思,把它当做奇怪的.难

柯里化函数之Javascript

柯里化函数之Javascript 定义 根据定义来说,柯里化就是将一个接收"多个"参数的函数拆分成一个或者许多个接收"单一"参数的函数.定义看起来是比较抽象的,下面来举个例子: 代码 1 2 3 4 5 function concat(str1,str2){ return str1 + str2; } concat("forever","px") // "foreverpx" 不难理解,上面的代码中定义了一

节流函数&防抖函数 柯里化函数

/* onscroll onresize input ..... 节流函数 让高频率事件进行减少触发变成低频率事件 var bStop = true; window.onscroll = function() { if(!bStop){ return; } bStop = false; setTimeout(()=>{ var t = document.documentElement.scrollTop || document.body.scrollTop; console.log(t); bS

柯里化函数、快速排序、外边距重叠

柯里化函数柯里化函数通常也称为部分求值,其含义是给函数分步传递参数,每次传递参数后部分应用参数,并返回一个更具体的函数接受剩下的参数,这中间可嵌套多层这样的接受部分函数参数,直至返回最后结果. 例子:实现carrying函数,完成以下需求,代码如下:function sum(a,b,c){return a+b+c;}function currying(fn){ `//todo`(自己编写的代码) }var curring = curring(sum);console.log(currying(s

关于柯里化函数

柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术. 特点: 参数复用 – 复用最初函数的第一个参数 提前返回 – 返回接受余下的参数且返回结果的新函数 延迟执行 – 返回新函数,等待执行 在编程开发中,使用柯里化函数封装解决问题的例子主要有: 兼容浏览器事件监听方法 性能优化:防抖和节流 兼容低版本IE的bind方法 例:设计一个柯里化函数(currying ),实现sum(100,200)(3

Scala中柯里化函数

高阶函数转一阶函数: val add1 = (x: Int) => x + 5 def add2(x: Int)(y: Int) = x + y //传入一个参数转换为一阶函数 def add3(x: Int) = (y: Int) => x + y val v2 = add2(2) _ //可以使用下划线转成一阶函数 //val v3 = add3(2) _ //无法转成一杰函数 val addx = (x: Int) => (y: Int) => x + y // val ad