Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

从 Rust 或 Kotlin 过来

Riddle 借用了 Rust 和 Kotlin 里好认的写法,但关键字相同不代表语义相同。下面只比较当前已经实现的行为。

速查

主题RiddleRustKotlin
函数fun add(x: i32) -> i32fn add(x: i32) -> i32fun add(x: Int): Int
不可变绑定let value = 1;let value = 1;val value = 1
可变绑定let mut value = 1;let mut value = 1;var value = 1
数据建模struct、enumstruct、enumclass、data class、enum class
共享行为trait + impltrait + impl接口、继承、扩展函数
分支匹配matchmatchwhen
可恢复失败Option、Result、?Option、Result、?可空类型与异常
可增长序列Vector<T>Vec<T>MutableList<T>
项目工具clue + Clue.tomlCargoGradle / Maven

相对 Rust

没有生命周期参数。 编译器自己追踪引用来源,判断值能不能留在栈上;引用需要活过当前栈帧时,值被提升到 GC 堆。移动后使用、借用冲突和 Drop 时序仍然按静态规则检查,GC 只影响存储位置。

没有 Box、Rc、Arc。 堆存储是自动的,共享一个值仍然靠引用,不靠引用计数。裸 dyn Trait 本身就是拥有所有权的值:开 GC 时分配在 GC 堆,关 GC 时走 riddle_alloc / riddle_free。

没有生命周期,也就没有生命周期标注带来的类型体操,泛型和方法解析更简单,代价是表达力下降:需要精确控制值何时被回收时,只能靠作用域和 Drop。

声明式宏(macro_rules!)不存在。 需要生成代码时写过程宏,见编写过程宏。

相对 Kotlin

fun 相同,块的返回值规则不同。 函数体的最后一个表达式就是返回值,不需要 return:

fun double(value: i32) -> i32 {
    value * 2
}

Kotlin 里等价写法要么用 return,要么写成单表达式函数。别因为都叫 fun 就照搬函数体规则。

没有类、可空类型和异常。 数据用结构体,共享行为用 trait 和 impl。可能缺失的值用 Option<T>,可恢复失败用 Result<T, E>,不可恢复路径用 panic。没有 null、throw、try、catch。

值会移动。 把非 Copy 值传出去之后原绑定就不能再用。提升到 GC 堆不会把值变成可以随便共享的对象,也不会取消借用检查。实现 Drop 的值在所有者结束时析构。

平台支持只有 C11 后端。 能否链接由目标组件和本机 C 工具链决定,没有 JVM、JS 或 Wasm 目标。

读外部教程时

Rust 和 Kotlin 的资料可以借来理解概念,但每段代码都要按形式化语法和当前工具链状态重新确认。名字相同的地方,边界条件往往不同。