likes
comments
collection
share

唠唠柯里化

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

前言

最近期末周也是烦的很,学校事情很多,再加上自己的状态不对浪费了很多时间...害,让我们停止躺平继续回到正轨,来唠唠柯里化!

正文

让我们思考一下,对于任意两数相加,我们是怎么实现的? 首先我们明确,既然是数的相加,那么参数的数量必须大于等于2; 其次,参数的传入形式必须是数字。 所以对于参数a,b来说,我们首先通过if判断参数的数量,在通过typeof判断参数的类型;为了使得判断结果语义化我们可以通过打印加上注释。

function add(a, b) {
    if (arguments.length < 2) {
        console.log('参数数量不够');
        return
    }
    if (typeof a !== 'number' || typeof b !== 'number') {
        console.log('类型错误');
        return
    }
    return a + b
}
console.log(add(2, 3));

如何使用闭包去接收参数实现参数的相加呢?要构成闭包我们首先需要两个函数,我们用第一个函数来接收第一个参数,用第二个函数来接收第二个参数,将第二个函数放在第一个函数的里面。这是第一步,我们需要得到a+b的值所以我们在内部函数(第二个函数里面)返回a+b,并且返回这个函数。

function add(a) {
    //第一个参数a,第二个参数b
    return function (b) {
        return a + b;
    }
}
console.log(add(2)(4));//6

这段代码实现了简单的“柯里化”技术

现在我们将难度再次升级,如果我传入的参数数量不定怎么办? 在这里我们不仅需要用到柯里化currying技术,还需要运用到ES6的rest运算符,为了使代码语义化我们使用args代表arguments即传入的参数。

  • rest 运算符...args会收集不定数量的参数形成数组传入函数中
const curry = (fn, ...args) => {
    console.log(...args);
}

function add(x, y, z, m) {
     return x + y + z + m;
}
curry(add, 1, 2, 3)

我们该如何理解这段代码呢?

  • 我们首先创建了一个柯里化函数,在这个函数里我们设置了形参fn和余下的参数...args;
  • 我们设置了相加的函数add来行使将传入add函数参数全部相加的功能;
  • 接着我们通过curry()调用了柯里化函数,我们传入了add和1,2,3进行形参和实参相统一,fn=add(function);
  • 接着执行cyrry函数,add函数被执行,实现参数相加的功能

值得注意的是,在curry函数中的...args和log中的...args的...的作用并不相同;其一是接受余下所有参数的rest运算符,另一个是解构。如果我们分别将args和...args打印的话结果也不相同

唠唠柯里化 你看,上面是一次打印的结果,...将传入的数组解构后再通过add函数相加最后得到结果10。

理解了通过柯里化来实现参数相加的原理后让我们来看一道面试题:

请用js内容实现:一个函数需要接受4个参数才能执行相加操作,否则返回一个函数

现在我们来构建这个函数,传入参数1,2,3,4,我们要思考,当参数数量不同时会导致两种结果所有这里需要一个判断,我们首先需要判断传入参数的数量,参数数量满足时能直接执行相加函数;当参数数量不够时等待下一个参数,我们该如何实现?

const curry = (fn, ...args) => {
    return args.length >= fn.length
        ? fn(...args)
        : (..._args) => curry(fn, ...args, ..._args)
}

// 原函数  需求
const add = (x, y, z, m) => {
    return x + y + z + m
}

console.log(curry(add, 1, 2, 3));

是的,运用递归,当参数不断传入时形参和实参不断统一。

参数的数量我们用三元运算符判断,当参数数量不够时将他放进一个新函数中,在这个函数中返回调用柯里化函数。我们用(..._args) 表示后续传入的参数,例如第一步我们给出参数1,2,3,这时参数数量不够就会走后面的函数,这时结果会返回这个未定义的函数,这个函数就是递归函数但是当我们再次传入参数比如4时,这个参数传入这个递归函数,他会接收这个参数(..._args)和之前传入的参数123合并然后重新调用柯里化函数,最终得到结果。

对于我们AI全栈工程师来说,当然还要其他的方法去解答这道题

我们可以开启一个全栈项目

创建一个gen_code文件夹,在这个文件夹里创建一个main.js项目,在集成终端中开启后端项目npm init -y,然后引入npm i openai库,开始全栈创作。

  • 首先,代码通过require方法导入了openai模块,这个模块允许开发者与OpenAI的API进行交互
  • 接着,使用提供的API密钥和自定义的baseUrl,这里使用的是我自己github的账号和密匙
const OpenAI = require('openai');

const client = new OpenAI({
apiKey: 'sk-0icNotaB0sMgI1xQmk5wAV4iXbgHSH9NV3zmAdI1OJPxFPBQ',
baseUrl: "https://api.chatanywhere.tech/v1" 
});
  • 立即执行异步函数 该函数内部包含了与OpenAI API交互的逻辑
(async () => { 
// ... 
})()
  • 使用了try-catch结构来尝试与OpenAI API通信 这种结构能够捕获并处理可能出现的错误
try { 
// ... 
} catch (err) { 
// 错误处理代码(当前为空)
}
  • 我们在构建的框架中向gpt3.5提出要求
  • 构建好代码的引用ai的基本框架
(async () => {
   
    try {
      
        const response = await client.chat.completions.create({
            model: 'gpt-3.5-turbo',
            messages: [
                {
                    role: 'system',
                    content: '假定你是一位专业的JavaScript工程师'
                },
                {
                    role: 'user',
                    content: `
                    请编写一个JavaScript函数实现柯里化
                    要求:函数名为curry
                    接受一个fn,以及余下的参数
                    如果接收到的参数数量达到fn需要的参数数量,
                    则运行fn,并拿到返回结果
                    否则递归调用curry,继续接受参数
                    添加必要的注释, 说明函数的功能
                    在函数未尾添加几个测试用例,并打印结果 
                    `
                }
            ]
        })
        console.log(response.choices[0].message.content);

    } catch (err) {

    }
})()

如上代码,就能自动帮我们生成我们所需要的代码。

转载自:https://juejin.cn/post/7380579033547669541
评论
请登录