[Day 3] Reactive Programming - Functional Programming

前言

并不是说Reactive 一定要搭配Functional,只是搭配起来更好用,而後面介绍到的Reactor & WebFlux,基本上也都是Functional Programming,所以在这边先介绍一下到底何谓Functional Programming。
https://ithelp.ithome.com.tw/upload/images/20210917/201414186PxQwB5fLm.png

图片来源 tail recursion

Functional Programming?

函式语言程序设计(英语:functional programming)或称函式程序设计、泛函编程,是一种编程范式,它将电脑运算视为函式运算,并且避免使用程序状态以及易变物件。其中,λ演算为该语言最重要的基础。而且,λ演算的函式可以接受函式作为输入参数和输出返回值。

上述源自於wiki,简单的说Functional Programming就是前一天介绍的Programming paradigm其中宣告式的一种,所以她其实就是一种抽象的概念,尽量透过函式来编写程序码,会有以下几个特性。

First-class citizen

值可以指定给变数,也可以当作参数传入方法(函数)中,则称为一级值(first-class value)。Java当中int、long、String或是物件等等都可以指定给变数并传入方法(函数),这些也就是first-class value,而能够指定给变数以及当作参数的函式,则被称为First-class citizen(一等公民), Java 8 之後,提供了FunctionsSuppliersConsumersPredicates等等Functional Interfaces,Java 才终於有了First-class citizen。

higher-order function

java 有了First-class citizen之後,随之而来就是higher-order function,当一个函式(function)传入一个或多个函式做为参数,他就是higher-order function,举例来说,在操作Stream的时候常用到的map()filter()flatMap().......等都是higher-order function,他们都是将函式做为参数。

@Override
public Stream<R> filter(Predicate<? super R> predicate) {
 return new StreamDecorator<R>( delegate.filter( predicate ), closeHandler );
}

@Override
public <R1> Stream<R1> map(Function<? super R, ? extends R1> mapper) {
 return new StreamDecorator<>( delegate.map( mapper ), closeHandler );
}

@Override
public IntStream mapToInt(ToIntFunction<? super R> mapper) {
 return new IntStreamDecorator(
   delegate.mapToInt( mapper ),
   closeHandler
 );
}

pure function

同样的input,一定会输出相同的output。

no(尽量不要有) side effects

大部分的说明都是没有副作用,避免状态或是资料改变,但现实中的企业应用专案,需要去log或是存入db资料,很难去做到完全的no side effects,所以追求最少的副作用是一个折衷的办法。

immutable

不可更改,也就是当物件的状态在创建後就不可以更动。

若遵守以上几个条件,当需要多处理并发(Concurrency)与多执行绪(Parallelism)的时候,程序相对就可以单纯许多,毕竟不会改变也就不用去synchronized,而在维运的时候也不会到处去找BUG是否是因为某个状态不如预期,可想而知这就是Functional Programming的优点之一。下面是一个简单的将偶数乘上5并加总的范例。

List<Integer> data = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Integer sum = data
    .stream()
    .filter(i -> i % 2 == 0)
    .map(i -> i * 5)
    .reduce(0, Integer::sum);
System.out.println(sum);
//150

结语

Java 本来的语言特性是更友善物件导向设计(OOP), OOP的特色就是万般皆物件,用物件的概念去对应并设计程序,比较好入门而且更具体一点不像是Functional 这麽抽象,另外OOP的重点在於资料(DATA),FP则关注於操作(operations),所以有人说若是资料多操作少建议使用OOP,资料少操作多则推荐使用FP。我个人的观点认为在JAVA中很难完全舍弃掉OOP,所以在OOP中去使用一些FP的写法或许是一个不错的办法。

对oop vs fp有兴趣可参考这篇

资料来源


<<:  {DAY5} SQLite操作练习

>>:  JavaScript学习日记 : Day5 - 基本型别(三)

Day04 - 在 GCE 建立第一个 Web Service

在 Day03 我们使用 GCE 建立一台 VM,今天要学习如何连线到虚拟机,并在服务器上使用 No...

[Day08] 团队系统设计 - 规画系统

在 Scrum Guide 中其实并没有明确地提到所谓的「精链会议」( Refinement) ,因...

Day.29 其他树的介绍

树有非常多变型,下面是Wiki的截图 以下简单介绍几种常听到的~ AVL Trees、Red Bla...

Day 01: ML基础第一步 Python基础入门

前言 Python是一种易於学习且功能强大的程序语言,可以呼叫使用相当完整的标准资料库,我们也称之为...

[Re:PixiJS - Day45] 不同时期的学习 PixiJS 的过程与真完赛心得

来到这系列的最後一篇,除了心得结语外,也讨论的学习 PixiJS 的过程 时期1:不考虑效能,这时期...