稀土掘金 android面试题,从一道面试题谈谈函数柯里化(Currying)

欢迎大家再一次来到我的文章专栏:从面试题中我们能学到什么,各位同行小伙伴是否已经开始了悠闲的春节假期呢?在这里提前祝大家鸡年大吉吧~哈哈,之前有人说,学面试题不会有什么长进,其实我觉得这个就像是我们英语考试中的阅读理解,带着问题去看文章反而更有利于自己的学习。

之前的两篇文章:

都在稀土掘金和Segmentfault都获得了非常多的点击量,没有看的小伙伴们可以点击了解一下,今天为大家带来一道关于闭包和函数的柯里化方面的编程题目,各位小伙伴有没有开始跃跃欲试呢?

编程题目的要求如下,完成plus函数,通过全部的测试用例。

'use strict';

function plus(n){

}

module.exports = plus

测试用例如下

'use strict';

var assert = require('assert')

var plus = require('../lib/assign-4')

describe('闭包应用',function(){

it('plus(0) === 0',function(){

assert.equal(0,plus(0).toString())

})

it('plus(1)(1)(2)(3)(5) === 12',function(){

assert.equal(12,plus(1)(1)(2)(3)(5).toString())

})

it('plus(1)(4)(2)(3) === 10',function(){

assert.equal(10,plus(1)(4)(2)(3).toString())

})

it('方法引用',function(){

var plus2 = plus(1)(1)

assert.equal(12,plus2(1)(4)(2)(3).toString())

})

})

实话说刚开始拿到这道题的时候我并没有完全的做出来,但是具体的思路是有的,肯定是关于函数的柯里化(Currying)方面的,应该是想考察一下面试者的闭包理解能力.

那么首先介绍一下什么是函数的柯里化(Currying)。《JavaScript忍者秘籍》一书中,对于柯里化的定义如下:

在一个函数中首先填充几个参数(然后再返回一个新函数)的技术称为柯里化(Currying。

维基百科中关于其定义如下:

在计算机科学中,柯里化(Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。这个技术由克里斯托弗·斯特雷奇以逻辑学家哈斯凯尔·加里命名的。

首先我们举个例子来具体的解释一下以上的概念。

例如一个最简单的加法函数:

//函数定义

function add(x,y){

return x + y;

}

//函数调用

add(3,4);//5

如果采用柯里化是怎样将接受两个参数的函数变成接受单一参数的函数呢,其实很简单如下:

//函数表达式定义

var add = function(x){

return function(y){

return x + y;

}

};

//函数调用

add(3)(4);

这样理解起来其实是不是就很简单了,其实实质利用的就是闭包的概念(大家可以在我的另一篇文章浅谈JavaScript闭包看一下)。本质上讲柯里化(Currying)只是一个理论模型,柯里化所要表达是:如果你固定某些参数,你将得到接受余下参数的一个函数,所以对于有两个变量的函数y^x,如果固定了y=2,则得到有一个变量的函数2^x。这就是求值策略中的部分求值策略。

柯里化(Currying)具有:延迟计算、参数复用、动态生成函数的作用。例如如果我们需要创建一个通用的DOM事件绑定函数,不使用柯里化的写法如下(该示例来自于博客园Tong Zeng):

//第四个参数用来标识是在冒泡阶段还是在捕获阶段执行函数

var addEvent = function(el,type,fn,capture){

if (window.addEventListener) {

el.addEventListener(type, function(e) {

fn.call(el, e);

}, capture);

} else if (window.attachEvent) {

el.attachEvent("on" + type, function(e) {

fn.call(el, e);

});

}

}

但是在使用了柯里化(Currying)的情况下,不再需要每次添加事件处理都要执行一遍if...else...判断,只需要在浏览器中判定一次就可以了,把根据一次判定之后的结果动态生成新的函数,以后就不必重新计算。其实在实际使用中使用最多的一个柯里化的例子就是Function.prototype.bind()函数,我们也一并给出一个较为简单的Function.prototype.bind()函数的实现方式。

Function.prototype.bind = function(){

var fn = this;

var args = Array.prototye.slice.call(arguments);

var context = args.shift();

return function(){

return fn.apply(context,

args.concat(Array.prototype.slice.call(arguments)));

};

};

回到我们的题目本身,其实根据测试用例我们可以发现,plus函数的要求就是接受单一函数,例如:

plus(1)(4)(2)(3).toString()

但是与柯里化不同之处在于,柯里化返回的一个新函数。我们观察其实最后的求值是通过toString函数得到的,那么我们就很容易想到,我们可以给返回的函数增加一个toString属性就可以了。我自己写出的答案如下:

/**

* Created by lei.wang on 2017/1/22.

*/

'use strict';

function plus(num) {

var adder = function () {

var _args = [];

var _adder = function _adder() {

[].push.apply(_args, [].slice.call(arguments));

return _adder;

};

_adder.toString = function () {

return _args.reduce(function (a, b) {

return a + b;

});

}

return _adder;

}

return adder()(num);

}

module.exports = plus;

运行一下,通过全部的测试用例,需要注意的是由于题目的要求运行在严格模式下,所以我们在_adder函数内部是不能引用arguments.callee,这时我们采用的方法是给函数表达式中函数本身起名_adder,这样就解决的这个问题。

再次感谢大家阅读本篇文章,希望大家能从中或多或少学到一些东西,入行资历甚浅,不足之处请多指教,欢迎大家在去我的博客MrErHu中留言打赏,愿大家一同进步。

  1460000008193610?w=1386&h=1026

深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值