唠唠柯里化
前言
最近期末周也是烦的很,学校事情很多,再加上自己的状态不对浪费了很多时间...害,让我们停止躺平继续回到正轨,来唠唠柯里化!
正文
让我们思考一下,对于任意两数相加,我们是怎么实现的? 首先我们明确,既然是数的相加,那么参数的数量必须大于等于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