当前位置: 首页 > 工具软件 > Typed Clojure > 使用案例 >

clojure和scala_Clojure in Action,第二版,评论和作者问答

杨飞
2023-12-01

clojure和scala

由阿米特·拉合尔(Amit Rahore)和弗朗西斯·阿维拉(Francis Avila)撰写的曼宁的《行动中Clojure》第二版》是对Clojure 1.6的重要,透彻和组织良好的介绍,它探讨了语言的核心部分,同时向读者介绍了Clojure的务实和惯用性质。 InfoQ与该书的合著者之一弗朗西斯·阿维拉(Francis Avila)进行了交谈。

第二版对Clojure 1.6进行了急需的更新,而第一版涵盖了Clojure 1.2。 在此过程中,关于一些外部库的各章已被其他人替换或已过时,并通过更广泛和重新关注Java-Clojure互操作性而被删除和替换,这证明了Clojure自从从更广泛的程序员社区(包括许多非Java程序员)那里获得的信息。

Clojure in Action旨在提供Clojure的完整而详细的介绍,而不会忘记它所生活的JVM生态系统,并且它是在一个有点敏捷的程序包中这样做的,最值得注意的是,不会发现不必要的信息重复。 本书采用了一种有趣的示例代码方法,在许多情况下,示例代码直接来自Clojure标准库,例如在讨论Clojure宏系统时,因此它们尽可能接近Clojure真实代码。 在其他情况下,示例则尝试构建可补充Clojure中现有抽象的抽象,例如在讨论多态性和协议时。

本书包含11章,从头开始涵盖语言,从数据结构,函数,条件,名称空间等构建模块开始,然后逐步转向更高级的主题,例如多方法,宏,协议,最后两章专门讨论两个特定的,高度相关的主题:如何在测试驱动的开发环境中使用Clojure,该技术集中于单元测试,存根和模拟。 如何使用编写高级宏和特定于域的语言(DSL)。

InfoQ与本书的共同作者之一弗朗西斯·阿维拉(Francis Avila)进行了交谈,以了解有关其书,Clojure的优势及其未来的更多信息。

InfoQ:您能解释一下写这本书的动机吗? 为什么有必要?

弗朗西斯·阿维拉(Francis Avila) :这本书的基本动机是帮助来自更主流编程背景(Java,C#,Python,Ruby,JavaScript等)的程序员学习Clojure及其核心哲学租户:精心管理状态和时间,默认情况下的不变性,尽可能地对数据进行纯功能转换,并将代码作为数据进行处理。 在撰写第一版时,这些想法还只是边缘,而阿米特·拉索尔(Amit Rathore)本质上是在旷野中的一个声音,试图引起人们对Clojure提供的优势的关注。 那些对Clojure感兴趣的人绝大多数来自Java背景,并且拥有庞大的Java生态系统来支持,但是他们想要一个更好的工具来管理这种复杂性。

第二版的当务之急是更新本书,以反映Clojure 1.6的更改。 (第一版是针对Clojure 1.2编写的。)但在随后的几年中,编程环境也发生了变化:不变性和函数式编程不再是完全陌生的想法(尤其是对于动态类型语言的实践者),并且Java之外的程序员也越来越多世界开始对Clojure感到好奇。 现在,本书的必要性是向广大程序员介绍Clojure。 具有讽刺意味的是,这意味着要成为Java和JVM的辩护者,这是动态语言背景的程序员所不熟悉的(并且受到怀疑)。 我知道,因为我是那些程序员之一!

InfoQ:您能简要介绍一下您的背景和您对Clojure的经验吗? 是什么导致您选择Clojure?

弗朗西斯:我的背景根本不是计算机科学,而是人文科学:哲学,神学以及古希腊语和拉丁语。 但是,我从小就是个极客,在大学里自学了Linux和Python。 毕业后,我成为一名Web开发人员,主要写PHP并结合了许多其他内容。 我发现Clojure在读布鲁斯·泰特(Bruce Tate)的《七周内的七种语言》一书。 (这是其中的一种语言。)我对Rich Hickey的关于不变性,状态和复杂性的想法感到非常兴奋,而且我对Clojure的研究越深入,我就越能肯定自己在管理大型复杂性方面所获得的口齿不清的直觉。软件项目。 (关于PHP项目的事情是,如果您不热衷于管理复杂性,它将很乐意管理您!)

最终,我发现所在地区的一家公司正在招聘Clojure开发人员,因此我于2012年中期申请并开始在Breeze工作。Breeze是一家位于路易斯安那州的小型电子健康记录公司,几乎完全使用Clojure和ClojureScript。

InfoQ:您的书针对的是没有Clojure或任何其他功能语言经验的开发人员。 您在阅读本书时会给他们什么建议? 他们应该期待什么? 他们不应该期待什么?

弗朗西斯(Francis) :我能提供的最重要的建议是,在您阅读和尝试问题时,请保持Clojure REPL的运行状态。 在边缘情况下戳一下,看看会发生什么。 如果您想节省一些键入操作,可以下载本书中的代码(按章整齐地排列在命名空间中)。 如果可以使用带有集成REPL的编辑器或IDE(例如Cursive(IntelliJ IDEA),LightTable或Proto REPL(Atom)),则此过程会更加流畅。 使用与编辑器集成的REPL,您可以编辑到文件或缓冲区中,并可以在进行过程中自动重新评估,重新定义和测试(即戳入)您的代码,而不必复制粘贴到命令行中。

如果您遵循此建议,那么在完成本文时,您将牢固地掌握Clojure的编写机制,如何从Clojure的角度来解决问题,以及Clojure的抽象工具包的哪些部分将在何时何地使用。 (例如,何时以及如何使用一流的功能,多重方法,协议和记录,宏等)。

但是,本书不会让您熟悉Clojure库的庞大生态系统和当今存在的系统级模式。 第一版对此进行了更加认真的尝试,但这是一种非常老旧的信息。 从那时起,这些库中的许多库要么发生了很大变化,要么已被更好的技术所取代。 与其更新这些部分,不如将它们缩小并更加专注于开发Clojure的核心能力,并将库依赖性降至最低。

InfoQ:您能否描述Clojure提供的一些功能,这些功能可以帮助程序员提高您的体验效率?

弗朗西斯(Francis) :Clojure中最大的生产力乘数是默认情况下丰富的不可变数据结构集。 不必担心“如果其他一些代码改变了这件事怎么办?” 或“什么代码更改了此代码?” 本身可以消除大量的错误和无用的大脑循环。 越来越多的时间以“小规模”进行编程变得更加容易,因此您将注意力集中在较小的功能上,并在以后进行整体组合。

将不可变性作为整个Clojure生态系统的默认假设,会对其他Clojure功能产生巨大的乘数效应,这些特征本身就可以了。 例如,Clojure提供的核心功能编程结构(映射,缩小等)使构建简单的,以数据为中心的转换管道变得容易,但是现在有许多语言都可以使用它们。 (甚至是Java!)但这种方法在与不可变数据结构结合使用时确实很实用,因为您可以自由,自信地重新安排和检查管道中的数据,而不必担心传播意外突变。

InfoQ:您的书对宏编程和DSL进行了大量介绍。 这使得材料更加先进。 您能解释一下为什么您决定加入这种更高级的资料吗?

弗朗西斯(Francis) :宏是Clojure(和一般来说是lisps)价值主张的关键部分,有效地使用它们是一项关键技能。 也就是说,使用宏创建DSL比使用其他语言中常见的技术要简单得多。 宏是关于控制已嵌入有效的Clojure程序中的表单(即评估前的代码为数据)的评估,因此,如果您必须编写自己的语法,则不必从头开始。词法分析器或解析器,AST和运行时。 相反,可以使用Clojure运行时的全部功能,并且您最关心的是添加自己的语法并将其就地扩展为可执行的Clojure。

此外,宏除了编写DSL之外还有更多通用用途。 每当您要发出计算结果而不是计算结果的代码(即“预编译”值)时,请用内联代码替换函数调用,或控制是否评估代码块以及以什么顺序进行计算(例如,在控制流构造中),您将需要编写一个宏,因此了解它们的工作原理非常重要。

InfoQ:您还提到了Clojure如何帮助最大限度地减少意外复杂性。 您能举一些实际的例子吗? 什么是意外复杂性,Clojure如何将其最小化?

弗朗西斯(Francis) :偶然的复杂性是我们为程序员为自己解决的那些问题赋予的名称。 “复杂性”与“简单性”形成对比:一个简单的想法是,在保留其原样的情况下不能将其删除。 一个复杂的想法仍然可以消除。 “偶然”与“本质”形成对比:复杂性不是要解决的问题的一部分(本质),而是解决问题的方式的一部分(偶然)。

Clojure通过提供更简单的抽象方法来减少意外的复杂性:不是在“更易于使用”的意义上“简单”,而是在“没有其他东西可被取走”的意义上。 通过两个对比示例更容易看出这一点。

在大多数编程语言中,集合(例如引用数组)是可变的:现在集合中有一些成员,但是以后可以有不同的成员。 这些集合是“复杂的”,因为它们结合了价值(即我拥有哪些成员),身份(我在内存中的地址是什么)和时间(我现在拥有的东西)。 如果您想共享此收藏集,则有人需要仔细复制它才能更改它(因为它的价值和身份不可分割)。 您也无法轻松地获取集合的快照,而不必在程序中的某个时刻复制整个“ Universe”。

在Clojure中,这三个需求由不同的抽象来满足。 集合(我一直在谈论的那些不可变的数据结构)只是值,因为它们不能更改,并且因为它们与其他集合的相等性并不取决于它们在内存中的地址是相同的,还是在基础实现上是相同的。 因为它们是不可变的,所以它们也是临时的:您确实可以在特定的时间“坚持”对程序整个状态的引用,而不会改变它。 值实际上是可以放置值的框“保留”的位置。 Clojure中有四种不同的类型,每种类型都涉及一种管理随时间变化的特定方法,例如异步与同步,协调与独立。 这些值箱仅具有标识,仅管理所需的特定种类的更改(即时间)。

在对Clojure进行了一些经验之后,您会发现,仅使用值和接受值并产生其他值的纯函数,几乎可以完全解决大多数问题。 只有少数几个地方需要突变所需的复杂性(必须将时间和身份结合在一起),在这些地方,您需要使用Clojure的一种参考类型(即值框)。 但是,大多数编程语言使您无论是否需要突变都付出了代价,并且这变成了与问题的解决无关的偶然复杂性,但仍然需要管理。

如果您想快速解释这些核心思想(状态,价值,时间,身份和行为)以及它们在Clojure与OO编程中的含义,我建议这篇博客文章“ Rich Hickey's Brain的非正式指南”

InfoQ:一个新的程序员,比如说必须要有背景的人,应该在语言的哪些领域给予更多的重视? 什么是最难学习的技能,以及如何做到最好?

弗朗西斯 :最难学习的技能是“软”技能:从数据转换而不是操作或动作的角度来思考程序。 练习此技能的一种方法是经常检查功能并重构:

  • 如果有副作用,请消除它。
  • 如果存在可变的var / ref / atom(尤其是本地变量),则将其消除。
  • 如果使用集合,请尝试重写它以仅使用集合中的一项,然后使用map或reduce(或其他序列函数)将其概括化。
  • 如果有中间结果,则需要绑定(使用let)并以特定顺序使用,请查看是否可以重新排列步骤或函数签名以使用线程宏。

InfoQ:公司采用Clojure可以期望相对或竞争优势吗? 而当前的主要挑战是什么?

弗朗西斯(Francis) :从企业角度来看,您可以用更少的代码和更少的开发人员来完成相同的工作,并且更小的代码库更易于更改。 您也将花费很少的精力就获得非常好的应用程序性能。 (这不是绝对最快的语言,但是它将非常接近Java,并且比Python或Ruby好一个数量级。)通常,Clojure在以数据为中心(以计算为中心)和需求经常变化的地方。 与Java开发人员相比,您将很难找到Clojure开发人员,但是您将不需要那么多开发人员。

但是,在许多问题域中,代码安全性或性能至关重要,并且要求是相当固定的。 有一些结构化类型(Prismatic模式)库或渐进式代数类型(Typed Clojure)库,但这些库是可选的或尚未完全成熟。 Clojure在电话或平板电脑等受限环境中也无法很好地工作。 (有一些针对小型客户端的相关替代方法,例如ClojureScript或Skummet。)

InfoQ:谈到Clojure在商业项目中的采用率越来越高,您认为推动这一趋势的最相关因素是什么?

弗朗西斯(Francis) :许多应用程序正在迁移到基于Web的部署,并且需要横向扩展而不是向上扩展,并且不变性使得横向扩展在微观级别(线程级别并发)和宏级别(集群)都容易得多。级别的一致性)。 因此,我认为这是促成其成功的因素之一。

另一个是它托管在JVM上。 一方面,有丰富的Java经验,专业知识和软件基础,​​但对Java企业生态系统的复杂性感到沮丧。 Clojure使您可以逐步实现简单性,而又不会丢掉所有东西:它比Java更简单,更具表现力,但仍可以与Java共存。 因此,对于一个对Java嵌套感到不满意但无法承受尝试完全不同的尝试的组织,Clojure是一个不错的选择。

另一方面,来自动态语言背景的人会因为Java的静态类型和复杂性而避免使用Java,因此他们认为Clojure是一种易于使用的语言,它也是动态类型的,并且具有一流的功能,其运行速度比其自己的语言快得多。 当今最流行的动态语言实现具有JVM所不具备的性能或并发限制(例如全局解释器锁定,或根本没有线程!),而Clojure为它们提供了一种利用JVM功能而又不至于过多的方法。 Java。

InfoQ:关于Clojure(语言)的发展方向有什么想法吗?

弗朗西斯(Francis) :我认为某些Clojure开发人员正在经历三种痛苦,这些痛苦会激发Clojure的未来发展。

首先,Clojure运行时很大并且启动缓慢。 在具有长期运行的应用程序的服务器环境中,这不是问题,但是越来越多的人希望将Clojure用于短期程序(例如命令行工具)或资源受限的机器(例如android手机)上。 Clojure的极端活力在这里是一个责任,因为它会使事情变慢。 Clojure 1.8添加了一个可选的编译设置,称为“直接链接”,当永不重新定义var时,它将删除var间接寻址。 这允许Clojure生成较小的Java类和更多的静态调用。 这有点帮助,但还不够。 可能会在将来的Clojure版本中使用的其他想法是:摇晃树(即消除死代码),以实现较小的代码大小;以及延迟加载名称空间,以加快启动速度。

其次,Clojure开始在更多主机上看到更多实现。 ClojureCLR(.NET上的Clojure)的发行时间与Clojure本身差不多,并且在过去的一年中ClojureScript的受欢迎程度呈爆炸式增长。 Clojure历史上一直以主机为中心,但是越来越多的开发人员希望编写Clojure代码,该代码至少可以在Clojure和ClojureScript之间移植。 (实际上,许多Clojure库都可以在任何环境下运行而无需修改。)Clojure 1.7引入了一项称为“阅读器条件”的功能,该功能允许根据Clojure的实现对同一.cljc文件中的代码段进行条件评估。 我希望有更多的努力来确保Clojure版本之间的平台差异保持最小。 例如,Clojure 1.8引入了附加的字符串函数,以消除调用某些Java方法的需要,并提高了Clojure和ClojureScript之间的代码可移植性。

最后,人们对代数类型,尤其是渐进类型越来越感兴趣。 程序员希望编译器验证类型和不变量,因此他们不必编写太多的测试。 但他们也不想被迫显式键入整个程序。 正如我所提到的,Clojure在此领域中已有工作。 Clojure中存在Prismatic Sc​​hema,Herbert和许多其他运行时结构类型库,并且Typed Clojure项目提供了可选的编译时渐进类型。 我预计这些项目(尤其是Type Clojure)将进一步成熟,并得到更广泛的采用。 但是,我不希望对Clojure核心进行任何更改来满足这些需求。

本书有电子版或印刷版两种版本,其风格在两章可免费下载的章节中得到了充分证明:《 介绍Clojure 》和第8章, 《函数编程》

翻译自: https://www.infoq.com/articles/clojure-in-action-2ed-review/?topicPageSponsorship=c1246725-b0a7-43a6-9ef9-68102c8d48e1

clojure和scala

 类似资料: