Function , Function > increaseBeforeApplyF = f -> x -> f.apply(x + 1);// 调用方式Integer y = increaseBeforeApplyF.apply(someFunction).apply(x);// 部分调用Function somePartialFunction = increaseBeforeApplyF.apply(someFunction);
/** 列表单层遍历修饰符 */private static final Function > traversalListF = f -> l -> IntStream.range(0, l.size()).forEach(i -> l.set(i, f.apply(l.get(i))));
我们可以用x -> x + 1去测试一下List<Integer> list = Arrays.asList(1, 2, 3),然后将list打印出来,看看我们写的遍历器有没有将元素各个加1。事实上,根本没有这个必要,也非常不“函数范儿”。事实上,测试的时候,我们只需要知道我们的函数确实遍历到了每个元素就可以了,具体遍历做什么并不重要。
/** 前置调用修饰符 */public static final Function > beforeF = f -> c -> o -> { c.accept(o); return f.apply(o); };
那么我们可以这样测试:遍历的对象原封不动,但是在此之前将他们打印出来。
/** 函数幺元 */private static final Function identity = o -> o;//测试List list = Arrays.asList(1, 2, 3);traversalListF.apply(beforeF.apply(identity).apply(System.out::println)).accept(list);// 输出123
同样,我们可以写一个afterF
/** 后置调用修饰符 */public static final Function > afterF = f -> c -> o -> { Object oo = f.apply(o); c.accept(oo); return oo; };// 测试traversalListF.apply(afterF.apply(beforeF.apply(x -> x + 1).apply(System.out::println)).apply(System.out::println)).accept(list);// 输出122334
/** 集合单层遍历修饰符 */private static final Function > traversalSetF = f -> s -> { List l = new ArrayList(s); traversalListF.apply(f).accept(l); s.clear(); s.addAll(l); };//测试Set set = new HashSet();set.add(1);set.add(2);set.add(3);traversalSetF.apply(x -> 1).accept(set);set.forEach(System.out::println);//输出1
/** 谓词: 属性在对象中是否static修饰 */private static final Predicate isStaticField = field -> Modifier.isStatic(field.getModifiers());/** 对象单层遍历器 */private static final Function traversalObjectF = f -> o -> Stream.of(o.getClass().getDeclaredFields()).forEach( field -> { if (isStaticField.test(field)) ; /* pass.accept(field) */ else modifyF.apply(f).apply(o).accept(field); });
我们测试一下:
class Person { private String name; private String englishName; private String age; private String sex; // ... oh, my god! a lot of get/set}//测试Person myDaughter = new Person();myDaughter.setName("Xinyu");myDaughter.setEnglishName("Alice");myDaughter.setAge("1");myDaughter.setSex("Female");traversalObjectF.apply(beforeF.apply(identity).apply(System.out::println)).accept(myDaughter);//输出XinyuAlice1Female
/** 谓词匹配修饰符 */public static final Function > matchingF = p -> f -> o -> p.test(o) ? f.apply(o) : o; /* identity.apply(o) *//** 类型匹配修饰符 */public static final Function > typeF = clazz -> matchingF.apply(o -> o.getClass().equals(clazz));
我们再测试一下:
class Person { private String name; private String englishName; private Long age; // Hope to live long private Boolean sex; // ... oh, my god! a lot of get/set}//测试Person myDaughter = new Person();myDaughter.setName("Xinyu");myDaughter.setEnglishName("Alice");myDaughter.setAge(1L);myDaughter.setSex(true);traversalObjectF.apply(afterF.apply(typeF.apply(String.class).apply(x -> "Hello, " + x)).apply(System.out::println)).accept(myDaughter);//输出Hello, XinyuHello, Alice1true
/** 单层遍历器字典 */private static final Map traversalFMap = new HashMap<>();static { traversalFMap.put(List.class, traversalListF); traversalFMap.put(Map.class, traversalMapF); traversalFMap.put(Set.class, traversalSetF);}private static final Function defaultTraversalF = traversalObjectF;/** 获取实现已知接口的遍历修饰符 */private static final Function
// nextTraversal = ?private static final Function depthTraversalF = f -> o -> isNull.test(o) ? o : /* identity.apply(o) */ isFinalClass.test(o) ? f.apply(o) : beforeF.apply(identity).apply(nextTraversal.apply(f)).apply(o);
/** 深度遍历修饰(双递归) */private static final Function depthTraversalF = f -> o -> isNull.test(o) ? o : /* identity.apply(o) */ isFinalClass.test(o) ? f.apply(o) : beforeF.apply(identity).apply(fullTraversal(f)).apply(o);/** 全遍历 */public static final Consumer fullTraversal (Function f) { return o -> getTraversalF.apply(o).apply(depthTraversalF.apply(f)).accept(o);}
测试一下
我们写个稍复杂的例子测试一下:
//测试:我的女儿家人有爸爸妈妈,和两个小狗朋友,爸爸的家人有爷爷和奶奶class Person { private String name; private Long age; // I hope we all live long private Map family; private List friends; // ... oh, my god! a lot of get/set}Person grandfather = new Person();grandfather.setName("Grandpa");Person grandmother = new Person();grandmother.setName("Grandma");Map myParents = new HashMap<>();myParents.put("grandfather", grandfather); myParents.put("grandmother", grandmother);Person me = new Person();me.setName("Larry"); me.setAge(30L);me.setFamily(myParents);Person lover = new Person();lover.setName("Lotus"); lover.setAge(30L);Map family = new HashMap<>();family.put("father", me); family.put("mother", lover);Person doggy = new Person();doggy.setName("Doggy"); doggy.setAge(2L);Person puppy = new Person();puppy.setName("Puppy"); puppy.setAge(3L);Person myDaughter = new Person();myDaughter.setName("Alice"); myDaughter.setAge(1L);myDaughter.setFamily(family);List friends = new ArrayList<>();friends.add(doggy); friends.add(puppy);myDaughter.setFriends(friends);fullTraversal(beforeF.apply(identity).apply(System.out::println)).accept(myDaughter);//输出Alice1Lotus30Larry30GrandmaGrandpaDoggy2Puppy3
常规的编程模式是通过向计算机下达指令,step by step,一步一步地完成某个功能。这种编程模式叫做命令式编程。但是事实上,“一步一步下达指令”是计算机擅长的事情,并不是人类擅长的。而我们今天采用的方式,是通过向计算机描述,来让计算机理解某项功能。这种编程模式叫做声明式编程。其实声明式编程也不是很罕见的东西,常用的SQL、XML/HTML/CSS都是声明式的(想想我们平时写的SQL语句是不是也只有一行)。
//猜想BiFunction trace = (property, lastQueue) -> ??; // push property into queue, and return queueBiFunction f = (o, latestQueue) -> ??; // handle object according to queue, and return object
M a c h i n e ( ∑ i = 1 n ( f i ) , s t a t e ( c s , l s ) ) . l o a d ( d a t a , i s ) , ( i s = 初 始 状 态 , c s = 当 前 状 态 , l s = 上 一 个 状 态 ) Machine(\sum_{i=1}^{n}(f_i), state(cs, ls)).load(data, is), (is = 初始状态, cs = 当前状态, ls = 上一个状态) Machine(i=1∑n(fi),state(cs,ls)).load(data,is),(is=初始状态,cs=当前状态,ls=上一个状态)