2024 Clojure状态调查!中分享您的看法。

欢迎!请参阅关于页面,了解有关该如何工作的更多信息。

+2
Clojure

我对Clojure的简洁性、多线程模型、语言稳定性以及出色的Java互操作性非常着迷。但我更喜欢静态类型,这对多开发者的项目非常有用。

TypeScript为JavaScript添加了一层出色的类型检查,有助于在编译时消除许多编程错误。它还打开了大量编辑器/IDE工具的可能性。我认为TypeScript是JS历史上最好的一件事。

我在想,Clojure核心团队或其他有能力和资源的团体是否在考虑为Clojure开发类似TypeScript的东西?

如果没有,为什么?

谢谢

1 答案

+5

Clojure核心团队没有计划为Clojure开发静态类型,因为我们认为这不是必要的。我们的重点是spec(《https://clojure.org/about/spec》),它为描述Clojure数据和函数的可选规范提供支持。

Typed Clojure 项目(https://typedclojure.org/)是由 Ambrose Bonnaire-Sergeant 进行的一项相当巨大的工作,他在攻读博士学位期间完成了这项工作。你可能还对 Spectrum(https://github.com/arohner/spectrum)感兴趣,它是一个基于规格的静态类型检查程序。据我所知,这两个项目都没有被广泛使用,也没有特别活跃的开发。

by
edited by
感谢回答。

我们确实研究过 spec,发现它主要是一个运行时的事务。它在文档和测试方面非常有帮助,但我个人认为它不能像类型系统那样做。

我们是一家小型的初创公司,有几名程序员。当我们开始时,我们认真考虑了 Clojure,但最后我们决定采用 Scala,因为它的强大类型系统。当需要 JS 时,我们也使用 TypeScript。

我相信许多 Clojure 粉丝都处于与我相同的情况。他们热爱它,并希望用它来做严肃的工作,但不得不选择其他语言,因为缺乏类型检查。为了澄清,我的意思并不是 Clojure 不是一个适合严肃工作的语言。我的意思是对于某些团队或公司来说,类型系统在选择语言或技术栈进行严肃项目时是一个重要的因素。

我理解 Clojure 是无类型的特性。但 TypeScript 表明,一个良好的类型系统可以为这种灵活且强大的无类型语言的生态系统增添巨大的价值。

顺便说一下,前几天我在 2017 年的一场 Clojure 会议中听了 Zach Tellman 有关抽象的技术演讲。我记得他分享了一个观点,即在 Lisp 语言家族中,包括 Clojure,在某种程度上太灵活,这可能是它成功的一个重要障碍。
by
TypeScript 并没有“证明”类型系统“增添巨大的价值”,但我想你的评论中的关键点是“对于某些团队...类型系统是一个重要因素”。而对于那些重视灵活性的团队,像 Clojure 这样的语言将比 Scala 更适应。

我在工作的公司尝试引入Scala,但类型系统对每个人都非常令人望而生畏,所以我们转向了Clojure。那是在差不多九年前,现在我们运营着四十多个在线约会网站,拥有数百万的顾客,这些网站都使用了完全基于Clojure的后端。我们发现Clojure提供的强大和灵活性使我们能够非常快速地进行系统和功能的更改和升级。在生产环境中,我们大量使用Spec进行输入验证,以及测试各种可能需要类型系统支持的事情。由于它可以以类型系统无法描述的方式描述形状和行为,因此它更为强大。
感谢分享你的见解。

我可以问一下你使用的Clojure Web框架是什么吗?

REST API服务是我们的服务的关键部分。我们曾经是Netty的忠实粉丝,在我们开始自己的商店之前,我们曾经在自己的Netty上运行了一个定制的REST API框架。因此,当我们开始的时候,我们希望选择基于Netty的Web/REST框架。我们对Clojure框架进行了评估,发现其中大部分都没有积极维护或者缺乏生产案例。我们最感兴趣的aleph似乎也已经被遗弃了。

这也是我们选择Scala的一个原因,因为它有Akka http。但我仍然渴望将Clojure引入其他项目,这正是你提到的原因。

关于你的技术栈的一些见解将非常有帮助。谢谢。
我另外补充一点,clj-kondo最近增加了一种简化类型检查的功能,也值得一试: https://github.com/borkdude/clj-kondo/blob/master/doc/types.md
就这一点来说,我相信 Aleph 在生产环境中被很多人成功使用。所以我会认为它是一个保险的选择。

不过,我怀疑目前最积极维护且支持netty(以及其他)的HTTP服务器可能是Pedestal: https://github.com/pedestal/pedestal

否则,Clojure中最受欢迎且积极维护的选择将是ring,带ring-jetty-adapter插件以配合使用Jetty服务器。

阅读以下指南以获取更多信息:[阅读指南](https://purelyfunctional.tv/mini-guide/clojure-web-servers/)

此外,您可以直接使用Netty,Clojure中的Java互操作性相当好,远比Scala的更好。因此,直接使用Java服务器接口也是一个不错的选择。
谢谢。

就像您说的那样,如果我们决定用Clojure启动某个项目,我们可能会直接使用Netty。我们在Netty之上进行了Java互操作实验,一切都很顺利。裸机方法会给我们更大的灵活性。
我们不用任何“框架”与Clojure结合。我们使用了一系列库。Ring几乎是一切的核心。我们在几乎所有应用程序中使用Compojure进行路由(我们在一个地方使用了Bidi)。我们主要使用内嵌的Jetty网络服务器(通过“标准”Ring适配器),但所有应用程序也可以根据命令行参数和环境变量启动http-kit。我们在一个高度依赖于SocketIO的应用程序中直接使用Netty。

我们还在大约十个服务中使用大量其他库的组合。其中一些包括服务器端渲染HTML -- 我们使用Selmer渲染几乎所有HTML,在另一个地方使用Hiccup从Clojure数据中渲染HTML片段。

2015年,我们原本考虑过将ClojureScript作为可能的选前端,但当时生态系统非常粗糙,工具感觉脆弱(当时,Clojure与ClojureScript之间的差距比现在大得多)。因此,我们决定使用JavaScript和React.js / Redux / Immutable.js等构建我们的客户应用程序。我们有一个专注于JavaScript的前端团队。

如果我们今天再次做同一个项目,我认为我们会再次评估ClojureScript作为严肃的竞争者,因为过去4-5年里生态系统已经发生了巨大变化。我不知道到时候我们会选择JavaScript还是cljs。
谢谢。这非常有帮助。我们也许也会考虑Clojurescript。

顺便问一下,我可以建议这个论坛的版主将关于clojure开发者在生产中分享技术栈和见解的帖子置顶吗?

我认为这对社区会有很大帮助。
by
我不会置顶它,但有一个关于技术栈的问题在https://ask.clojure.org/index.php/8280/what-is-your-clojure-and-clojurescript-stack
by
非常有帮助,谢谢
by
编辑了 by
我认为这里可能存在一些误解。
"静态类型,这对于有多个开发者的项目来说非常有帮助"
"Clojure核心团队没有计划为Clojure添加静态类型,因为我们认为这不是必需的。我们的工作重点在于spec(《https://clojure.org/about/spec)”)

AFAIU(根据我的理解,如果错误请纠正),发帖者请求的是“设计时类型”,而答案涉及了类似于Java理解的静态类型。

我和可能的问题作者所寻找的是要编写
 
(defn describe-dog [^:happy-puppy-co.api/dog dog]
      (println (str (:breed dog) (:age dog))))

并且让智能感知拾取&nbps;:happy-puppy-co.api/dog spec并基于其键及其相应的子spec提供提示。也就是说,帮助我像作者预期的那样使用::dog,而无需查看其文件。

TypeScript在编译后不存在,其输出是JavaScript。TypeScript最大的好处是它可以帮助你更快地理解他人的代码(并提供一些避免误用的帮助,但这是次要的)。
by
我觉得你的评论并不完全符合原始问题,但如果你在询问与函数定义集成的规范,那正是我们在spec 2中考虑的事情。
by
那么,怎么解释以下内容呢?

“我是静态类型的……粉丝,这对拥有超过几个开发人员的项目非常有帮助。”

TypeScript也为编辑器/ IDE 工具提供了许多可能性。我可以说,TypeScript是发生给JS的最好事情。”

按照我的理解,这意味着您必须始终与大量代码打交道,这些代码既不是您自己,也不是您的团队之前编写或审查过的。企业应用程序通常具有数十个具有30多个键的dtos,并具有非常不一致的命名方式。典型的思考过程是这样的:“好吧,我们的函数将接收一个 'sales-deal' dto,我需要将其转换为 'financing-deal' 并发送到分析平台,'sales-deal' 上的利润率属性叫什么?是 'margin' 还是 'markup' 或仅仅是 'rate'?并且它是已经是一个小数,还是作为项化费率组件 sub-dto 存在?”然后为 'financing-deal' 进行相同的一套问题...

我绝对同意“历史上发生给JS的最好事情”这一部分。遗憾的是,尝试使用ClojureScript的感觉像是回到JS——并不好。我赞赏spec的力量,以及它如何帮助我在运行时和测试时。我现在想做的是,利用所有的这些力量,将其插入到我的IDE中,以帮助我编写代码。如果还没有编写代码,那就没有什么是可以运行或测试的。
by
顺便说一句,为了更好地说明我在寻找什么,请查看这个库: https://github.com/vriad/zod
它允许你定义类似spec的方案,这些方案在设计/编译期间也被TS编译器所理解和使用。

// spec定义 - 在TS编译后存在,可用于验证方案
const dogSchema = z.object({
  name: z.string(),
  阉割: z.boolean(),
});

// 在运行时验证模式
const cujo = dogSchema.parse({
  name: 'Cujo',
  neutered: true,
}); // 通过验证,返回 Dog

// TypeScript 类型定义 - 在 TS 编译后不存在
type Dog = z.infer<typeof dogSchema>;
/*
等价于
type Dog = {
  name: string;
  neutered: boolean;
}
*/

// 使用推断的类型进行编译时类型检查和设计时智能提示
const fido: Dog = {
  name: 'Fido',
}; // TypeError: 缺少必需的属性 `neutered`
...