首先来看下什么是函数式编程,举个例子:
[view mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.bottom.left.right.equalTo(self.view);
}];
这里的
make.top.bottom.left.right.equalTo(self.view);
就是典型的函数式编程。
那么什么是链式编程呢,这种.top.bottom.left.right.equalTo(self.view)通过"."语法,将需要执行的代码连续的书写,就叫做链式编程,它使得代码简单易懂。
而这种.equalTo(self.view)通过"()"来实现函数的调用,就是函数式编程。
比如我们要实现一个加减乘除的函数式编程,用来计算(2+3-1)*3/4的结果:
先看下最后实现的效果
float result = self.add(2).add(3).minus(1).multiply(3).divide(4).giveMeResult;
现在我们开从最简单的开始写起:
第一种方法:
@interface ViewController : UIViewController
@property (nonatomic,assign) float tmp;
- (void)add:(float)value;
- (void)minus:(float)value;
- (void)multiply:(float)value;
- (void)divide:(float)value;
- (float)giveMeResult;
@end
实现上述方法
- (void)add:(float)value
{
_tmp += value;
}
- (void)minus:(float)value
{
_tmp -= value;
}
- (void)multiply:(float)value
{
_tmp *= value;
}
- (void)divide:(float)value
{
_tmp /= value;
}
- (float)giveMeResult
{
return _tmp;
}
那么用这种写法,我们调用的话就是这样
[self add:2];
[self add:3];
[self minus:1];
[self multiply:3];
[self divide:4];
float result = [self giveMeResult];
emmmmm,也还看的过去吧,接下来我们稍微改造下:
第二种方法:
@interface ViewController : UIViewController
@property (nonatomic,assign) float tmp;
- (float)add:(float)value;
- (float)minus:(float)value;
- (float)multiply:(float)value;
- (float)divide:(float)value;
- (float)giveMeResult;
@end
实现上述方法
- (float)add:(float)value
{
_tmp += value;
return _tmp;
}
- (float)minus:(float)value
{
_tmp -= value;
return _tmp;
}
- (float)multiply:(float)value
{
_tmp *= value;
return _tmp;
}
- (float)divide:(float)value
{
_tmp /= value;
return _tmp;
}
- (float)giveMeResult
{
return _tmp;
}
那么用这种写法,我们调用的话就是这样
float result = ([self add:2] + [self add:3] + [self minus:1])*[self multiply:3]/[self divide:4];
2019-04-22更新 多谢No_00指出,这里如果直接打印
result
结果为44,因为[self add:2]
之后,结果为2,然后[self add:3]
,结果为_tmp+3=5,以此类推result=(2+5+4)*12/3
也就是44。
当然,如No_00所说,这里的返回值可以写成return self
,这样的话,最终就可以写成((((self.add(2)).add(3)).minus(1)).multiply(3)).divide(4)
,更趋近于函数式编程。为了循序渐进,所以本文采用四步法一步一步进行改造,方便理解。
哟,看起来初见端倪了,那么接下来我们就用block来实现"()"的调用方法,这次我们就不用上面的主动传参的方法了,而是放在block内部
第三种方法:
@interface ViewController : UIViewController
- (void (^)(float))add;
- (void (^)(float))minus;
- (void (^)(float))multiply;
- (void (^)(float))divide;
- (float)giveMeResult;
- (void)initUI;
@end
- (void (^)(float))add
{
__weak typeof(self) wself = self;
void (^result)(float) = ^(float value){
wself.tmp += value;
};
return result;
}
- (void (^)(float))minus
{
__weak typeof(self) wself = self;
void (^result)(float) = ^(float value){
wself.tmp -= value;
};
return result;
}
- (void (^)(float))multiply
{
__weak typeof(self) wself = self;
void (^result)(float) = ^(float value){
wself.tmp *= value;
};
return result;
}
- (void (^)(float))divide
{
__weak typeof(self) wself = self;
void (^result)(float) = ^(float value){
wself.tmp /= value;
};
return result;
}
- (float)giveMeResult
{
return self.tmp;
}
我们来分析一下,这里所有的方法都返回的是一个block,请眼尖的同学不要拿- (float)giveMeResult跟我抬杠啊,你个杠精。当我们调用[self add]的时候,返回的是一个block,我们假定是这样
void (^AddResult)(float) = [self add];
那么如何执行这个block呢?聪明的你肯定知道
AddResult();
好,由于这是一个带参的block,那么我们传进去参数
AddResult(1);
但是,搞来搞去不是还要带上"[]"这个累赘吗?是啊,真的很蛋疼,但是大家想一下我们的"."语法的本质是什么,就是函数的隐式调用,我可以[self add],我也可以self.add!
什么,你不信?我多年的百度、谷歌、github经验能骗你?
好了,我们来实现下开始的计算:
self.add(2);
self.add(3);
self.minus(1);
self.multiply(3);
self.divide(4);
float result = self.giveMeResult;/*好吧,杠精有意见,看着不舒服,不这样写了,这位杠精朋友放学先别走,咱们谈谈人生,聊聊理想*/
float result = [self giveMeResult];
不错不错,基本上已经可以了,但是怎么能把这些实现串起来呢,跟着我的思路走:
self.add原本返回的是一个block,而self.add(2)返回的是void,如果我们能让他返回self,那么就可以使用这个返回值继续add(3)等其他操作了,沿着这个思路,我们进行最终的改造
退下,我要开始装逼了
第四种写法
@interface ViewController : UIViewController
- (ViewController *(^)(float))add;
- (ViewController *(^)(float))minus;
- (ViewController *(^)(float))multiply;
- (ViewController *(^)(float))divide;
- (float)giveMeResult;
@end
实现方法
- (ViewController *(^)(float))add
{
__weak typeof(self) wself = self;
ViewController *(^result)(float) = ^(float value){
wself.tmp += value;
return self;
};
return result;
}
- (ViewController *(^)(float))minus
{
__weak typeof(self) wself = self;
ViewController *(^result)(float) = ^(float value){
wself.tmp -= value;
return self;
};
return result;
}
- (ViewController *(^)(float))multiply
{
__weak typeof(self) wself = self;
ViewController *(^result)(float) = ^(float value){
wself.tmp *= value;
return self;
};
return result;
}
- (ViewController *(^)(float))divide
{
__weak typeof(self) wself = self;
ViewController *(^result)(float) = ^(float value){
wself.tmp /= value;
return self;
};
return result;
}
- (float)giveMeResult{
return self.tmp;
}
好了,大功告成,多谢大家的观看。
还不懂?艾玛,行吧,我就多说几句。
上面已经解释过了,当我们调用[self add]或者self.add的时候返回的是一个block,如果我们要执行这个block的话,需要self.add(1),执行了block的话,返回值就是block返回的结果(艾玛,有点绕嘴呢)。
我们拆分来看这个函数
- (ViewController *(^)(float))add
{
__weak typeof(self) wself = self;
ViewController *(^result)(float) = ^(float value){
wself.tmp += value;
return self;
};
return result;
}
函数add的返回值是一个block,block的返回值是一个ViewController,当我们调用了self.add的时候,就返回了这个ViewController *(^)(float)类型的block,一旦我们self.add()加了这个(),block就被执行了,执行的返回值就是一个ViewController,也就是block内部的返回值self,所以self.add()的返回值就是self,既然已经是self了,调用自己的函数也就不过分了吧,那么就可以继续self.add().add().add().minus()等操作了
综上所述,我们要计算的东西的实现就是
float result = self.add(2).add(3).minus(1).multiply(3).divide(4).giveMeResult;