likes
comments
collection
share

函数式编程中高频面试题-柯理化

作者站长头像
站长
· 阅读数 16

大家好,我是梦兽编程。一位分享编程经验和解决方案的UP主,UP主会经常在网上分享一下项目的经验,如果感兴趣,可以关注一下。如果你是一位爱看视频的极客,可以关注一下B站梦兽编程

柯理化

柯理化是函数范式必不可缺的一个功能之一,也是衡量你对函数式编程的理解的指标之一。所以它自然成为了某些团队的高频面试题。

但在国内真正落实这种思路的没几个,也是面试造火箭罢了。如果你是喜欢函数范式的同学那请一定要了解一下颗粒化。你看UP现在的头发,就知道柯理化帮up主保护了多少头发!

要理解函数柯里化,最好的方法就是看它的实际应用和作用。最简单的应用就是参数复用。

function uri(protocol, hostname, pathname) {
    return `${protocol},${hostname},${pathname}`
}

const uri1 = uri('https://',"www.rexweb.site","/dir");

console.log(uri)

上面的例子中,我们有三个参数组成一个函数。这里可我们发现没什么问题,但是如果我们有多个类似的网址的时候。我们就会出现很多重复的参数,在编码的过程中可以会出现一下的情况。

const uri1 = uri('https://',"www.rexweb.site","/点赞");
const uri2 = uri('https://',"www.rexweb.site","/收藏");
const uri3 = uri('https://',"www.rexweb.site","/点赞");

可以看出其实https://其实是一个高频的复用参数,我们能不能利用某些特性让它缓存起来呢?

使用闭包进行函数参数的复用

function uri(protocol) {
  return ( hostname, pathname) => {
    return `${protocol},${hostname},${pathname}`;
  };
}

const uri_https = uri('https')

const uri1 = uri_https("www.rexweb.link","/点赞")
const uri2 = uri_https("www.rexweb.link","/收藏")
const uri3 = uri_https("www.rexweb.link","/投币")

这样,函数中的https://的协议参数我们就得到了复用。使用闭包有什么好处,会在下一次的分享中进行说明。现在关注梦兽编程立刻得到最新动态。

延迟执行

柯理化还有一个很重要的作用就是延迟执行。在某些情况下就是对参数的复用功能进行改进。 这里就直接上面试题并且解释延迟执行。

add(1,2,3) = 6
add(1,2,3)(4) = 10
add(1,2,3,4,5) = 15

如果很熟悉柯理化的同学很容易看到这道题的猫腻,这里需要做到传入参数的时候不能进行限制,也不能丢失传入的参数。什么时候传入参数都可以!这样就增加了不少难度,因为我们不能无脑的不断进行参数返回函数的操作。

我们要如何解决这一类的问题呢?

function add() {
  let args = arguments;
  let inner = function () {
    (args as any).push(...arguments);
  };

  return inner;
}

这样我们发现好像解决函数返回函数的问题,但真的是如此吗?但我们

add(1)(2) // Error

我们要如何解决呢?

function add() {
  let args = Array.prototype.slice.call(arguments);
  let inner = function () {
    (args as any).push(...arguments);
  };

  return inner;
}

这样之后我们发现我们得到的结果是undefined 那是正常的,因为我们inner没有进行返回值与累加,我们要如何处理呢?

function add() {
  let args = Array.prototype.slice.call(arguments);
  let inner = function () {
    (args as any).push(...arguments);
    let sum = (args as any[]).reduce((g,cur)=> g+ cur);
    return sum;
  };

  return inner;
}

这样做好像实现了功能,但我们如果加多一个参数呢?

add(1)(2)(3)

发现还是error了,还是没有办法实现任意延迟输入参数,实际上每次增加一个括号的,我们都需要增加一个内部函数。这样我们就要增加无数个内部函数,这样是不现实的。这个时候就可以使用递归解决了。

function add() {
  let args = Array.prototype.slice.call(arguments);
  let inner = function () {
    (args as any).push(...arguments);
    return inner
  };

  inner.toString = function(){
    let sum = (args as any[]).reduce((g,cur)=> g+ cur);
    return sum;
  }

  return inner;
}

这样就能解决所有问题了,如果你看得很迷茫,不去B站观看视频。

今天的内容到这里就已经结束了,如果对你的学习和编程有什么帮助或者编程启发,不妨给up点赞投币收藏,三连一下。你的三连是创中最大的动力,这里是梦兽编程,口号保护头发根据地。

本文使用 markdown.com.cn 排版