2024 Clojure现状调查!中分享您的想法。

欢迎!请查看关于页面以了解更多关于其如何运作的信息。

+2
Clojure

我非常喜欢Clojure,因为它的简洁性、多线程模型、语言稳定性以及出色的Java互操作性。但我对静态类型更感兴趣,这对拥有多名开发者的项目来说非常有帮助。

TypeScript为JS添加了一层优秀的类型检查,有望在编译时消除许多编程错误。它还开辟了许多编辑器 / 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)感兴趣,它是基于spec的静态类型检查。据我所知,这两个项目都没有得到广泛的使用,也不特别活跃。


编辑了
感谢回答。

我们研究过规范,发现这主要是一个运行时问题。这对文档和测试非常有帮助,但在我看来,它不能像类型系统那样做。

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

我确信许多Clojure爱好者都和我一样。他们都很喜欢它,并希望用它来完成严肃的工作,但由于缺乏类型检查,他们不得不选择其他语言。为了澄清,我并不是说Clojure不适合严肃的工作。我的意思是,对于某些团队或公司来说,类型系统在选择语言或技术栈时是一个重要的因素。

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

顺便说一下,我最近看到一篇关于2017年Clojure会议上的技术演讲《抽象》,演讲人是Zach Tellman。我记得他分享了一个观点,即Lisp语言家族(包括Clojure),过于灵活,这在一定程度上阻碍了它的更大成功。
TypeScript并没有“证明”类型系统“添加巨大的价值”,但我认为你评论中的关键点是“对于某些团队……类型系统是一个重要因素”。而对于那些重视灵活性的团队,Clojure这样的语言比Scala更适合。

在我工作的地方,我们尝试引入Scala,的类型系统让大家都很不悦,所以我们转而使用Clojure。那是在大约九年前,现在我们运行着数十个在线约会网站,拥有数百万客户,完全使用Clojure后端。我们发现它提供的强大功能和灵活性使我们能够非常快速地更改和增强系统。我们在生产环境中大量使用Spec来进行输入验证,以及在测试中用于所有那些可能会依赖类型系统的事情,但它更强大,因为它可以描述形状和行为的各个方面,这是类型系统无法做到的。
感谢分享您的见解。

我能问您您正在使用的Clojure Web框架是什么吗?

REST API 服务是我们服务的关键部分。我们在Netty上曾是忠实粉丝,曾经在Netty上运行了自定义的REST API框架。因此,当我们开始建立自己的框架时,我们希望选择基于Netty的Web/REST框架。我们对Clojure的框架进行了评估,发现许多Clojure Web框架没有得到积极的维护或者缺乏生产案例。我们最感兴趣的框架 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://github.com/ring-clojure/ring

阅读更多内容,我建议您阅读这篇指南: https://purelyfunctional.tv/mini-guide/clojure-web-servers/

请注意,您还可以直接使用Netty。Clojure的Java互操作性相当好,比Scala的好很多。因此,直接使用Java服务器接口也不是一个太坏的选择。
by
谢谢。

正如您说的,如果我们决定用Clojure开始某事,我们可能会直接使用Netty。我们在Netty上层进行了一些Java互操作实验,一切都很顺利。裸机方法会给我们带来更多的灵活性。
by
我们不使用Clojure的任何“框架”。我们使用一系列库的组合。Ring是几乎所有功能的核心。我们在几乎所有的应用程序中使用Compojure进行路由(在一个中使用Bidi)。我们主要使用内置的Jetty网络服务器(通过“标准”Ring适配器),但我们的所有应用程序也可以启动http-kit,基于命令行参数和/或环境变量。我们直接使用Netty为某个高度依赖于SocketIO的应用程序。

我们在约十几项服务中使用了大量不同组合的库。其中一些是服务器端渲染的HTML -- 我们几乎用Selmer进行所有HTML渲染,Hiccup在其中一个地方用于从Clojure数据渲染HTML片段。

我们最初在2015年考虑将ClojureScript作为可能的备用前端,但那时的生态系统非常粗糙,工具似乎很脆弱(当时Clojure和ClojureScript之间的差异比现在大得多)。因此,我们决定使用JS和React.js / Redux / Immutable.js等构建我们的客户面向的应用程序。我们有一个专门的JS前端团队。

如果我们今天再次做同样的项目,我认为我们会再次评估ClojureScript作为一个严肃的竞争者,因为生态系统在过去4-5年中发生了巨大变化。我不知道届时我们会选择JS还是 cljs。
by
谢谢。这非常有用。我们可能会查看Clojurescript。

顺便问一下,我可以建议这个论坛的版主把这个主题固定在顶部,以便clojure开发者可以分享有关技术栈和见解的生产经验吗?

我认为这对社区将非常有帮助。
非常有帮助。谢谢

编辑了
我认为这里有一个误会
"静态类型,对于有多个开发者的项目来说非常有帮助"
"Clojure 核心团队没有计划为 Clojure 开发静态类型,因为我们认为它不是必需的。我们的努力集中在 spec (https://clojure.org/about/spec))

据我所知,如果我说错了请纠正我,发帖者是在询问 "设计时类型",而答案则涉及了像 Java 那样的静态类型。

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

并让 intellisense 检测到  :happy-puppy-co.api/dog spec,并根据其键及其各自的次规范提供提示。即,帮助我像其作者打算的那样使用 ::dog,而不必查看其文件。

TypeScript 编译后会不存在,它的输出是 JavaScript。TS 最大的好处是它可以帮助你更快地了解他人的代码(并且提供一些避免误用的帮助,但这只是次要的)。
我觉得你发的评论和原问题并不一致,但如果你在寻求和函数定义结合在一起的规范,那么这正是我们在规范2中考虑的内容。
那下面这个应该如何解读呢?

我是静态类型的拥趸,这对有多个开发者的项目非常有帮助。

TypeScript 同样为编辑器/IDE 工具带来了众多的可能性。我会说 TypeScript 是发生给 JavaScript 的最好事情。

我认为这表示需要不断地与大量的代码打交道,这些代码既不是你写的,也不是你的团队能写或审阅过的。企业应用通常有几十个包含30个以上键的 dto,而且命名非常不一致。典型的思维过程是这样的:“好吧,我们的函数将获取一个‘sales-deal’ dto,我需要将它转换成‘financing-deal’并发送给分析,‘sales-deal’上的利润率属性叫什么?是‘margin’、‘markup’还是简单的‘rate’?而且它已经是小数还是仍然以详细项目的比率组件格式存储?”然后对‘financing-deal’也会有类似的问题...

我完全赞同“发生给 JavaScript 的最好事情”的部分。遗憾的是,尝试 ClojureScript 似乎就像回到了 JavaScript 时代——这并不好。我欣赏 spec 的强大之处以及它在运行时和测试中的帮助。我现在想做到的是,利用所有这些功能,将它们融入到我的 IDE 中,以帮助我编写代码。如果没有写出来,就没有运行或测试的可能。
顺便说一句,为了更好地说明我所寻求的内容,请查看这个库: https://github.com/vriad/zod
它允许你设计类似规范的模式,这些模式也可以在设计和编译时被 TypeScript 编译器理解和使用。

// 规范定义 - 在 TypeScript 编译后存在,可用于验证模式
const dogSchema = z.object({
  name: z.string(),
  neutered: z.boolean(),
});

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

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

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