Pkl 是什么
Pkl 是一门面向配置的新型领域编程语言,致力于解决配置复杂化比如配置重复和错误验证等问题,主要面向云原生和应用配置等场景,其技术产品整体的主要目标可以概括为:
- 安全性:通过在部署之前捕获验证错误来提供安全性。
- 可扩展:语言整体既可以用在简单场景也可以用在复杂的场景中。
- 可编程:借助一流的 IDE 支持,提升配置代码编写体验。
KCL 是什么
KCL 是一个开源的基于约束的记录及函数语言,作为沙盒项目托管在 CNCF 基金会。KCL 通过成熟的编程语言技术和实践来改进对大量繁杂配置比如云原生 Kubernetes 配置场景的编写,致力于构建围绕配置的更好的模块化、扩展性和稳定性,更简单的逻辑编写,以及更简单的自动化和生态工具集成。
Pkl 和 KCL 的区别
设计理念
两个语言的设计理念可以从各自官网的 Slogan 窥见一二,Pkl 的 Slogan 是 Programmable, Scalable 和 Safe,KCL 的 Slogan 是 Mutation, Validation 和 Abstraction。可以简单理解为 KCL 相比于 Pkl 更聚焦在云原生领域中的具体场景问题比如复杂性和安全等问题,并更加贴近云原生的描述方式 (Mutation 和 Validation 取自 Kubernetes 中的 MutationWebhook 和 ValidationWebhook, 使用抽象 Abstraction 来对抗复杂性问题),对于非领域内的问题尽可能收敛语言自身的设计,减少一些不必要的设计并针对特定领域进行增强,以在满足功能以及开发者使用简单的基础上,尽可能参考一些使用起来比较简单的语言如 Python, Go 等语法语义风格,排除非预期的特性和副作用,比如从语言技术和 GitOps 结合两个方面加强对稳定性和一致性的保证,通过语言的自动化 API 来提升效率,通过强不可变性、冲突监测保证配置的确定性,通过代码复用和抽象结合默认值填充的方式屏蔽用户侧细节感知,通过自定义的校验表达式支持对配置数据的业务校验等,通过与更多的云原生工具或者项目集成比如 Kustomize, Helm 和 Crossplane 等来完成更多的场景功能支持。
而 Pkl 比在设计层面相比 KCL 更加 “通用” 和 “现代”,这不仅体现在语言设计元素上,还体现在具体的语言特性上。因为 Pkl 首先被设计为是图灵完备的,整体语言设计更像 Swift 和 Kotlin,这意味着 Pkl 不仅可以被用于主业 "配置" 场景,它还可以做的更多,比如你可以用它来写 Leetcode 算法题,编写快速排序。甚至你可以在 Pkl 中看到像 Java 那样的面向对象特性的一系列关键字以及在其他常用通用编程语言中不常见到的管道运算符 |>
。此外,Pkl 的很多特性和工具也都是 Pkl 自身实现的,这一定程度上体现了 Pkl 的能力。当然这样的用例有很多,无法在这里详尽一一列举。
我本人是十分喜欢 Pkl 这样的具有更多现代特性的语言的,这意味的它功能很强大,几乎不会出现满足不了的业务场景,对写库的开发者来说会比较容易接受。但是从反面的角度来说,这无疑为一门领域语言带来了额外的复杂性和推广学习门槛。而 KCL 会从配置数据和强大的通用语言特性之间把握一个平衡,比如 KCL 没有像 Pkl 那样的过程式 for 循环,KCL 虽然提供了偏面向对象的语言特性,但并不会引入像 Pkl 那样复杂的继承链和多态,并且 KCL 又参考了一些函数式语言,它的函数被设计为 "纯" 的,不会带来额外的副作用,这使得 KCL 可以在完成复杂功能的同时又可以像 JSON, YAML 等数据那样被上层业务系统集成实现以更多的自动化。这意味着 KCL 会舍弃最复杂的极端场景而选择比较场景的场景,并针对常用的场景提供了许多内置库函数可以使用。
语言特性
综合来看,KCL 和 Pkl 都支持变量定义、引用、类型定义,但支持程度和语法语义有差异;基本都支持支持常用的算术、逻辑、循环推导式、条件、函数、标准库和导入第三方模块等编程语言特性,支持方式及语法也各不相同,但都有从通用编程语言借鉴吸收;在用户自定义类型、面向对象的特性上部分支持或混合支持,在数据文件集成方面,KCL 和 Pkl 可以直接导入 JSON/YAML 数据类型和 JSON Schema 和 Kubernetes CRD 等类型定义。
此外,KCL 和 Pkl 都在配置操作 Patch, 数据验证和安全合规层面内置了许多语言特性满足配置的场景需求,比如支持配置的自动合并特性以及字段范围,类型,正则表达式等检查特性,不同是 KCL 采用了偏面向对象的特性,将数据的类型检查和约束检查分离,可以使得 KCL 提供更多的静态分析能力满足 IDE 或者其他工具链需要并或者组合约束检查的能力,而 Pkl 需要将约束定义与其类型定义书写在一起并统一在运行时完成类型检查和约束校验。
开发者工具
在开发者工具方面,Pkl 和 KCL 都是重视 Developer Productivity 的项目,提供了非常多的语言工具和 IDE 插件支持。除了基本的语言工具,Pkl 官网主要提供了三种 IDE 插件支持,分别是 IntelliJ, NeoVim 和 VS Code。巧合的是,KCL 目前也是提供了这三种 IDE 插件支持,不过它们的功能和侧重点略有不同。
Pkl 由于项目本身是 Java 和 Kotlin 开发,因此非常容易适配到 JetBrain 系列 IDE 插件体系中,因此 IntelliJ 插件支持最为完善,而 Pkl 本身并没有提供 Language Server,因此 NeoVim 和 VS Code 插件仅基于 Tree Sitter 解析器生成器提供了最基本的高亮和代码折叠,并无更高级的定义跳转、代码重构和补全等功能。另外 Pkl 虽然作为苹果的项目,但是没有使用 Swift 开发 Pkl 也没有为 XCode 开发 Pkl IDE 插件。
而 KCL 的情况正好相反,KCL 项目是 Rust 开发,并提供了 Language Server 支持,因此可以比较容易扩展集成到除 VS Code 的 IDE 插件支持包括 NeoVim 以及一些其他新兴的支持 LSP 的 IDE 或者编辑器。并且 KCL 基于 Language Server 提供了完整的代码高亮、补全、跳转、重构、补全和快速修复等功能。由于 IntelliJ 仅在在其专业版中提供了阉割的 LSP 支持,因此我们针对 IntelliJ 插件也补充了相应的功能 Java 实现支持,但是相比于 VS Code KCL 插件功能上目前没有那么完善,还有较多的提升空间。
总之,Pkl 和 KCL 在 Developer Productivity 方面也都有提升和完善的空间,由于不同 IDE 插件实现上的差异,这块需要更多从开源社区借力不断完善 IDE 体验和场景工作流程。
多语言 SDK
为了将配置语言更好地集成到用户的应用中,Pkl 提供了 Java, Kotlin, Swift 和 Go 四种多语言的绑定。又比较巧合的是 KCL 也提供了四种 SDK 💦, 分别是 Go, Python, Java 和 Rust。
是在 Pkl 开源之前,KCL 是为数不多甚至是唯一官方提供了多种 IDE 插件和多语言绑定,并且是在社区用户和研发者的共同敦促和努力一点一点积累做出来的。Pkl 在核心维护者这么少的情况下一开源就提供了许多可以和 KCL 对标的特性,可以想到在背后也迭代了相当久的时间,付出了相当多的努力,值得点赞。
受限于篇幅,以上内容不足以描述全部的设计细节和功能对比,下面仅列出一个表格对比用于读者参考。
特性 | Pkl | KCL |
---|
开源协议 | Apache-2.0 | Apache-2.0 |
开发语言 | Java, Kotlin | Rust |
语言风格 | 类 Swift, Kotlin | 类 Python, Go |
语言功能 | 强 | 中等 |
编译执行方式 | JIT | AOT |
运行性能 | 中等 | 中等 |
增量编译 | ✅ | ✅ |
标准库 | ✅ | ✅ |
包管理工具 | ✅ | ✅ |
格式化工具 | ❌ | ✅ |
文档工具 | ❌ | ✅ |
测试工具 | ✅ | ✅ |
调试工具 | ❌ | ❌ |
IDE 插件 | IntelliJ, NeoVim, VS Code | IntelliJ, NeoVim, VS Code |
多语言 SDK | Java, Kotlin, Swift, Go | Go, Python, Java, Rust |
多语言插件 | ❌ | Go, Python |
Language Server | ❌ | ✅ |
Spring 框架支持 | ✅ | ❌ |
OCI Registry 支持 | ❌ | ✅ |
社区模型库 | ✅ | ✅ |
REST Server 支持 | ✅ | ✅ |
导出配置数据 | JSON, YAML, TOML, plist 等 | JSON, YAML |
从其他数据或 Schema 导入 | ✅ | ✅ |
Kubernetes 配置支持 | ✅ | ✅ |
云原生工具集成支持 | ❌ | ✅ |