Clojure

理念

客户和利益相关者在行业标准平台(如 JVM)上投入了大量资金,并且对这些平台的性能、安全性和稳定性感到满意。虽然 Java 开发人员可能羡慕动态语言的简洁性、灵活性和生产力,但他们也担心在客户批准的基础设施上运行、访问其现有的代码库和库以及性能问题。此外,他们还面临着使用原生线程和锁处理并发的持续问题。Clojure 试图在这个背景下进行务实的动态语言设计。它力求成为一种通用语言,适用于 Java 适用的那些领域。它反映了这样一个现实,即对于并发的未来,普遍的、不受控制的变异必须停止。

Clojure 通过以下方式实现其目标:拥抱行业标准的开放平台 - JVM;对久负盛名的语言 Lisp 进行现代化改造;使用不可变的持久数据结构来促进函数式编程;并通过软件事务内存和异步代理提供内置的并发支持。其结果是健壮、实用且快速。

Clojure 对状态和标识有独特的方法。

为什么选择 Clojure?

我为什么要编写另一种编程语言?基本上是因为我想要

  • 一种 Lisp

  • 用于函数式编程

  • 与已建立的平台共生

  • 专为并发而设计

而找不到合适的。以下是 Clojure 背后一些驱动思想的概述。

Lisp 是一件好事

  • 经常被模仿/剽窃,但从未被复制

  • λ 演算产生了极其小的核心

  • 几乎没有语法

  • 核心优势仍然是代码即数据和语法抽象

  • 标准 Lisp(Common Lisp 和 Scheme)怎么样?

    • 标准化后发展缓慢/缺乏创新

    • 核心数据结构可变,不可扩展

    • 规范中没有并发

    • JVM 已经存在良好的实现(ABCL、Kawa、SISC 等)

    • 标准 Lisp 是它们自己的平台

  • Clojure 是一种不受向后兼容性约束的 Lisp

    • 将代码即数据的范式扩展到映射和向量

    • 默认使用不可变性

    • 核心数据结构是可扩展的抽象

    • 拥抱平台 (JVM)

函数式编程是一件好事

  • 不可变数据 + 一等函数

  • 始终可以通过 Lisp 的纪律/约定来实现

    • 但如果数据结构*可以*被修改,则认为它不会被修改是危险的

    • 在传统 Lisp 中,只有列表数据结构是结构递归的

  • 纯函数式语言倾向于强静态类型

    • 并非所有人都适用,也并非所有任务都适用

  • Clojure 是一种具有动态特性的函数式语言

    • 所有数据结构都是不可变且持久的,支持递归

    • 异构集合,返回类型

    • 动态多态

语言和平台

  • 虚拟机,而不是操作系统,是未来的平台,提供

    • 类型系统

      • 动态强制和安全

      • 抽象掉操作系统

      • 庞大的功能集

      • 内置和第三方

    • 内存和其他资源管理

      • GC 是平台,而不是语言,功能

    • 字节码 + JIT 编译

      • 抽象掉硬件

  • 语言即平台与语言 + 平台

    • 旧方法 - 每种语言都定义自己的运行时

      • GC、字节码、类型系统、库等

    • 新方法 (JVM、.Net)

      • 独立于语言的通用运行时

  • 为平台构建的语言与移植到平台的语言

    • 许多新语言仍然采用“语言即平台”的方法

    • 移植时,存在平台上平台的问题

      • 内存管理、类型系统、线程问题

      • 库重复

      • 如果原始语言基于 C,则一些用 C 编写的扩展库不会移植过来

  • 平台由客户决定

    • “必须在 JVM 上运行”或 .Net 与“必须在 Unix 上运行”或 Windows

    • JVM 拥有成熟的记录和信任级别

      • 现在也是开源的

    • 需要与其他代码互操作

      • 如今,C 链接已不足够

  • Java/JVM 语言 + 平台

    • 这不是最初的故事,但 JVM 的其他语言一直存在,现在被 Sun 接受

    • Java 可能很冗长,表达能力不足

      • 缺乏一等函数,没有类型推断等

    • 调用/使用 Java 的能力至关重要

  • Clojure 是语言,JVM 是平台

面向对象被高估了

  • 诞生于模拟,现在用于所有场合,即使在不合适的情况下

    • 由于 Java/C# 缺乏对其他任何事物的(惯用)支持,因此在所有情况下都鼓励使用它

  • 可变的有状态对象是新的意大利面条代码

    • 难以理解、测试和推理

    • 并发灾难

  • 继承不是实现多态的唯一途径

  • “让 100 个函数操作一个数据结构,比让 10 个函数操作 10 个数据结构更好。” - Alan J. Perlis

  • Clojure 将其数据结构建模为由接口表示的不可变对象,否则不提供自己的类系统。

  • 许多函数定义在少数主要数据结构上(seq、map、vector、set)。

  • 在 Java 中编写 Java,从 Clojure 中使用和扩展 Java。

多态是一件好事

  • switch 语句、结构匹配等会导致脆弱的系统

  • 多态产生可扩展、灵活的系统

  • Clojure 多方法将多态与 OO 和类型解耦

    • 支持多种分类法

    • 通过静态、动态或外部属性、元数据等进行分派

并发和多核未来

  • 不可变性使许多问题消失

    • 在线程之间自由共享

  • 但更改状态对于模拟以及程序内代理到外部世界的现实是必须的

  • 锁定很难一遍又一遍地正确处理

  • Clojure 的软件事务内存和代理系统负责处理难题

简而言之,我认为 Clojure 作为一种具有强大并发支持的 JVM 函数式 Lisp 占据了一个独特的利基市场。查看一些特性开始使用 Clojure