在Java 8里面实现了简单的「模式匹配」
所以最近其实在做的小实验是试着在Java8里面实现简单的模式匹配功能。也许说是模式匹配更像是Kotlin的when语句吧。
主要因为近期比较多开发和维护基于Java或JS这种经典技术栈的存在代码,然后因为之前的开发者看得出来是写惯了Java8这种上古语言的,所以代码风格很古老,经常会写着写着就想,要是有个模式匹配就好了。
也觉得如果有模式匹配确实会很好玩吧,同时也算是为了实践自己「把Java当作一个实现原型和研究的平台」的思路。
上次的文章讨论了关于发布打包和GitHub actions的事情,这次就写写一些关于这个模式匹配库本身的碎碎念吧。
其实Java17已经有了自带的模式匹配功能,而且还相当好用。但是,一方面现在的大部分Java项目仍然停留在8或者11的时代,另一方面,哪怕有了Java17,以Java程序员压倒性的保守态度,引入模式匹配风格写法并不是他们的首要考虑。
换句话说,在可见的未来,if (foo instance of Foo1) { Foo1 foo1 = (Foo1) foo … }
这种风格的嵌套if和强制转换仍然是大量Java开发者的条件反射和主要写法,更不用说很多软件也许会永远停留于Java8版本。
那么这个小类库的意义是什么呢?
首先当然是为了说明封装和抽象的作用,不过不是从应用层的角度,而是从语义的角度。用一个class的篇幅,来把「嵌套if语句+强转」封装为模式匹配,这意味着,哪怕在Java8这种语法死板表现力有限的地方,我们也可以「创造自己的语言/DSL」,来提供更具有声明式风格的语法。
这个用Java开发者习惯说的术语,也许算是「发明新的设计模式」?anyway,这并不重要。
当然,完整版的模式匹配也包括嵌套类型的解构和复杂模式的组合,这也许是基于Java8的语义永远无法做到的。有些模式匹配库试图利用注解等东西来绕过,但这本身其实也让模式匹配这件事变得毫无意义——注解只在运行期能被提取,而模式匹配的一大特点是数据的形状在静态分析的时候已经知晓。
换句话说,就是,type safety。
但是我们仍然可以做一些有趣的东西,比如说,常量、列表的匹配,补充条件,兜底匹配,之类的,最终,也许我们可以做到类似Kotlin的when语句的能力?
然后,为了实现这些补充的功能,大概率会需要引入visitor pattern,不过,比起用户手动维护和操作visitor pattern的细节,一个模式匹配库可以提供更直观的API,当然,还有type safety。
这里也有一个细节就是visitor pattern是否要返回值还是void了,或者,the type safety of visitor patterns。有空再说。
某种程度上,这也算是我一直想说的东西吧,就是质疑和超越「设计模式」。
说到底,语言和语法,并不仅仅是语法糖,这是和程序项目息息相关的东西。就像自然语言会塑造着说话人的文化背景,编程语言也在反作用于开发者对代码、抽象逻辑、程序的思考。
如果用软工常常喜欢说的cognitive complexity和cyclomatic complexity来说的话,也许也蛮有趣的吧。
也许还有一个有趣的角度吧,就是,我们需要什么样的安全性。
有人觉得只有严格遵循strict positivity的编程语言才是有意义的,换句话说,Scala、ML、Haskell都是做坏了的。
有人觉得类型系统是不可接受的。
不同的程序员也许有不同的态度。
不过也许可以换个视角呢?模式匹配的声明式API,可以是类型安全的,但是,在背后实现它的时候,或许也可以用更动态的方式逃逸Java过于死板的语法和语义带来的限制。
从这个角度讲,我们确实不需要在什么地方都要用上GADT或rankNtype。
所以这也是为什么我对Java语言的定位是「一个可以用来探索和研究的平台」而不是开发企业级应用的web框架的原因吧。