说实话,刚开始看这篇博客的时候,我甚至以为自己出现了幻觉。

AI配图

你有没有过这种 既视感?当你盯着一段 Swift 代码看,脑子里跳出来的却是 Rust 的逻辑;或者你在写 Rust 时,总觉得这语法和 Swift 哪怕不是亲兄弟,至少也得是表亲。

最近这篇《Swift is a more convenient Rust》在圈子里传疯了,作者抛出了一个相当大胆的观点:**Swift 本质上就是一个披着 C 语言外衣、更顺手、更“偷懒”的 Rust。**乍一听像是引战,但细琢磨下去,这背后的逻辑简直让人头皮发麻。

偷师还是致敬?

咱们先别急着站队,看看这两门语言的“家底”。

Rust 是什么?系统编程的当红炸子鸡,主打一个“快”字,还有那个让无数程序员掉头发的所有权机制。它发明了所有权这玩意儿来解决内存问题,既不要垃圾回收(GC),也不要引用计数,直接在编译期就把内存管得死死的。

Swift 呢?大家印象里它就是苹果的亲儿子,用来写 iOS 和 macOS 应用。但作者发现,这两者像得离谱。

Swift 也有来自函数式语言的特性,比如标记枚举、match 表达式(虽然它叫 switch)、头等函数,以及强大的泛型类型系统。

Swift 也能在没有垃圾回收器的情况下提供完整的类型安全。默认情况下,一切都是具有“写时复制”语义的值类型。

甚至连底子都一样——两者都基于 LLVM 编译器,都能编译成原生代码和 WebAssembly。

这哪里是巧合,简直就是“像素级致敬”。## 语法糖里的“骗局”

有意思的是,Swift 似乎在玩一种很新的“欺骗”游戏。

Rust 喜欢把它的函数式血统摆在脸上,那个 match 表达式写起来就透着一股学术范儿。但 Swift 不一样,它把这些高深的玩意儿藏在了大家熟悉的 C 语言语法里。

你看这个例子,Rust 写个枚举匹配:

AI配图

enum Coin { Penny, Nickel, Dime, Quarter, }
fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter => 25,
}
}

到了 Swift 这里,变成了这样:

enum Coin {
case penny, nickel, dime, quarter
}
func valueInCents(coin: Coin) -> Int {
switch coin {
case .penny: 1
case .nickel: 5
case .dime: 10
case .quarter: 25
}
}
```看出来了吗?Swift `match` 换成了 `switch`。这名字你熟吧?C 语言、Java 里都有。

但千万别被它骗了,Swift `switch` 根本不是传统的 `switch`。它不会“掉线”,它支持模式匹配,**它本质上就是个披着马甲的 `match` 表达式。**

这就好比 Swift 跟你说:“来吧,这就是你熟悉的 C 风格代码”,等你上手了才发现,哎?我怎么已经在写函数式编程了?甚至连处理空值(Null)都一样。Rust `Option`Swift `T?`。虽然 Swift 有个 `nil`,看起来像传统语言,但编译器会强迫你检查它,这不就是 Rust `None` 换了个皮吗?

## 一个是苦行僧,一个是享乐派

虽然底子像,但这俩语言的“性格”完全是反着的。

作者在博客里打了个特别精准的比方:**Rust 是自底向上的,Swift 是自顶向下的。**这话怎么理解?

Rust 的心是系统级的,它默认让你用所有权模型,追求极致的性能。你需要快,你就得忍受编译器的唠叨和复杂的语法。

Swift 呢?它默认让你爽。

默认情况下,Swift 所有东西都是值类型,自动用“写时复制”。这相当于你在 Rust 里把所有东西都包进 `Cow`Clone on Write)里一样。

> **Rust 默认更快,Swift 默认更简单。**

你想在 Rust 里偷懒用引用计数?行,你得自己写 `Rc``Arc`,还得手动 `unwrap`。但在 Swift 里,这一切都是自动的。这就好比 Rust 是个严厉的教练,逼你做深蹲练肌肉;Swift 是个贴心的管家,先把车开到你面前,等你真的想飙车了,再让你自己握方向盘。

## 编译器的“保姆”逻辑

我个人觉得,这两者最大的区别在于对待问题的态度。

举个具体的例子:写一个树形结构的枚举。

Rust 里,因为类型递归,编译器会直接报错,逼着你去用 `Box` 指针来分配内存,把问题显式地摆在你面前让你解决。

```rust
enum TreeNode {
Leaf(i32),
Branch<Vec<Box<TreeNode>>>,
}
```这很 Rust**它负责抓出问题,你自己负责解决。**

到了 Swift 里,你只需要加一个 `indirect` 关键字,剩下的编译器全包圆了。

```swift
indirect enum TreeNode {
case leaf(Int)
case branch([TreeNode])
}

你看,Swift 的编译器不仅抓问题,还顺手帮你把问题解决了。你不需要去想什么 BoxRc,代码写出来就是那么丝滑。

这就是代价。

Swift 把复杂性都藏进了黑盒子里,语言变得不那么“纯粹”,功能也越来越臃肿——什么类、继承、async-await、Actor、属性包装器……简直是个大杂烩。但老实讲,对于只想快速把产品做出来的开发者来说,这种“不纯粹”有时候真挺香的。

别再把它当成苹果的玩具了

很多人对 Swift 的偏见还停留在“只能写 iOS 应用”上。

这观念早该扔进垃圾桶了。

现在的 Swift,野心大得很。它早就跨出了苹果的围墙:Linux 上跑服务器,Windows 上跑浏览器(Arc 浏览器就是用 Swift 写的 Windows 版),甚至连 WebAssembly 和嵌入式设备(Panic Playdate)都通吃。> The Browser Company 甚至直言:互操作性是 Swift 的超能力。

而且,苹果也没把 Swift 捂在怀里。Swift 的核心团队正在努力改善非苹果平台的体验,VS Code 的插件支持也越来越好。

虽然评论区的老哥们也吐槽得在理:Xcode 在处理大型项目时还是容易卡成 PPT,包管理工具 SPM 跟 Rust 的 Cargo 比起来还是显得有点稚嫩,宏支持也不够完善。但这都是时间问题。

便捷是有代价的

说到底,天下没有免费的午餐。

Swift 让你写得爽,编译器帮你干了脏活累活,代价就是——默认情况下,它就是没 Rust 快。

Rust 是让你手动挡飙车,Swift 是给你开了个自动驾驶。你想在 Swift 里追求极致性能?行,那你得手动去管理所有权,去优化内存,这时候你会发现,其实你还是在写 Rust。

但这并不妨碍它们各自发光发热。Rust 依然会是操作系统、浏览器引擎、嵌入式系统的王者;而 Swift,凭借它的易用性和对开发者的友好,在 UI 开发、服务端甚至跨平台领域,会越来越像那个“更方便的 Rust”。

以后别再问“Rust 和 Swift 选哪个”了。

想追求极致掌控感,去拥抱 Rust 的严厉;想早点下班把产品上线,Swift 或许就是那个披着羊皮的狼,等着你发现它的好。

参考链接:
https://nmn.sh/blog/2023-10-02-swift-is-the-more-convenient-rust