Functor组合, 参数集合, Curry

Functor组合, 参数集合, Curry

Ajoo曾经写过面向组合子编程系列。我也帮着助威。
面向组合子编程和并不是简单意义上的Composite Pattern。Composite Pattern只是一个简单的基本Pattern。
面向组合子编程只是用到了Composite Pattern,面向组合子编程本身的内容复杂许多,以至于复杂到这样的程度,数据和行为必须分开,形成Visitor Pattern。
而一般意义上的Compositor Pattern都是数据和行为在一起的对象的组合。
用于面向组合子编程中,一般是指只有行为没有数据的Functor对象进行组合。

基本的模型是这样。包括3个参与部分。算法,Functor算子,参数。
算法基本上是固定的,Functor算子可能自由组合,参数也可能一个或者多个。

下面根据Functor和参数这两个方面介绍面向组合子编程的3种类型。

1. Functor组合 – Combinator, Pipe
Functor有多个,参数只有一个。
这一类的特点是,Functor移动,参数不动。

这是最常见的一类。
常见于用于工作流程控制的逻辑组合子。for each, or, and, not, if, else 等。
Hibernate的 Criteria Query 的 And , Or , Like, Equals的组合,也属于这一类。


ForEachCombinator( param ){ // And, Or
for( functor in functors ){
… functor( param); …
// do some thing.
// 比如, or 的时候,第一个符合条件,就返回
// and 的时候,第一个不符合条件,就返回
}
}

ForEachCombinator可以扩展为 OrCombinator,AndCombinator。

比较有趣的是,Pipe这种类型。
Pipe也是多个Functor,一个参数。但和上述的For each 之类的Combinator不同的是,下一个Functor的参数,是上一个Functor的返回结果。


Pipe( param ){
for( functor in functors ){
param = functor( param);
// do some thing.
}
}


我们给Pipe模式加上一些逻辑判断,和其他的Combinator组合,就可以用来实现if, then之类复杂一些的条件组合逻辑。
比如,我们给Pipe加上一个中断条件。

Pipe( param ){
for( functor in functors ){
param = functor( param);
if(param is not valid) // null, false, etc
break;
}
}


pipe = new Pipe( {new Equls(1), new Printer });
表示参数是1的时候,会执行printer。
pipe(1) 就可以打。
pipe(2) 就不打印。

这里只是一个简单示意。比较详细的例子和实现,可以看ajoo的blog和帖子。

2. 参数集合 – Visitor, Map, Filter, Reduce
这一类比较有趣。参数是多个,是一个集合,Functor可以是一个(也可能是多个)。
这一类的特点是,Functor不动,参数移动。

FP的Map, Filter算法都是这样,接受一个集合参数(list, stream),都经过同一个Functor的处理,当然这个Functor本身可能是组合过的。
Reduce算法也是这样,只是有点不同。Reduce多了一个Continuation, Context作用的环境变量参数,这个参数上一次处理的结果,传递给同一个Functor的下一次调用。
自己产生参数,自己消费,这个行为模式,和Pipe有点类似。但是不同。
Reduce算法反复调用一个Functor,并遍历参数集合。Pipe调用多个Functor,而且每个Functor只调用一次。

3. Functor组合,参数集合 – Curry, Factory Chain
最复杂的类型,就是这一类了。Functor移动,参数也移动。

关于Curry的概念和例子,本文不展开。网上有不少好文章。可以搜索到。
Curry 很类似于 Factory Chain。
举个例子。F(x, y, z) = 2 * x + y - z。
F(1, 2, 3)
用Curry的方式写就是,f(1)(2)(3)。这是FP语法。
换成类似于c, java, c#的语法来写,就是Factory Chain的写法。
factory.generate(1).generate(2).generate(3);

这里的关键是,上一个Functor处理参数的结果产生了下一个Functor。
下一个Functor继续处理下一个参数,产生下一个Functor。

BigDecimal.add(…).add(…).multiply(…).substract(…)
StringBuffer.append(…).append(…)
factory.newSession(..).newQuery(…).setParameter(…).setParameter(…)

等等形式,都具有Curry, Factory Chain的形式特点。虽然有时候,Functor返回的是自己。

Design Pattern的 Abstract Factory ( Factory of Factor ) 可以扩展成 Factory of Factor of Factory .., 就成了Factory Chain。也具有Curry, Factory Chain的形式特点。

Curry, Factory Chain在问题降维(减少参数个数)方面有很大用处。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值