for
SKILL.md
仓颉语言 for-in 迭代 Skill
1. for-in 基本语法
1.1 语法
for (item in sequence) {
exprs
}
sequence须实现Iterable<T>接口sequence表达式仅在首次迭代前求值一次- 循环表达式类型为
Unit,值为()
1.2 执行流程
- 求值
sequence,调用iterator()获取迭代器 - 调用迭代器
next():返回None则退出循环,返回Some(value)则继续 - 将
value绑定到item,执行循环体 - 回到步骤 2
1.3 迭代变量规则
- 迭代变量
item不可变(let绑定),不能在循环体中重新赋值 - 若循环体中不使用迭代变量,可用通配符
_占位避免警告:for (_ in 0..3) { println("hello") }
2. Range 区间类型
2.1 区间字面量
- 半开区间(左闭右开):
start..end— 不包含end - 闭区间(左闭右闭):
start..=end— 包含end - 可选步长
: step,省略时默认为 1;step 不能为 0
for (i in 0..5) { print(i) } // 输出:01234
for (i in 0..=5) { print(i) } // 输出:012345
for (i in 0..10 : 2) { print(i) } // 输出:02468
2.2 逆向与步长
- 负步长实现逆序迭代:
for (i in 5..0 : -1) { print(i) } // 输出:54321
for (i in 10..0 : -3) { print(i) } // 输出:10741
2.3 空区间
step > 0 && start >= end(半开)或step > 0 && start > end(闭)→ 空区间,循环体不执行step < 0 && start <= end(半开)或step < 0 && start < end(闭)→ 空区间
2.4 Range 类型签名
public struct Range<T> <: Iterable<T> where T <: Countable<T> & Comparable<T> & Equatable<T>
start: T、end: T、step: Int64isEmpty()判断是否为空;iterator()返回迭代器
3. Iterable 与 Iterator 接口
3.1 接口定义
interface Iterable<T> {
func iterator(): Iterator<T>
}
interface Iterator<T> <: Iterable<T> {
mut func next(): Option<T>
}
Iterator自身扩展Iterable,可直接用于 for-innext()返回Some(value)表示有元素,None表示迭代结束
3.2 for-in 脱糖
for (i in list) { println(i) }
等价于:
var it = list.iterator()
while (let Some(i) <- it.next()) {
println(i)
}
3.3 已实现 Iterable 的内置类型
| 类型 | 元素类型 | 有序 |
|---|---|---|
Range<T> |
T |
✅ |
Array<T> |
T |
✅ |
ArrayList<T> |
T |
✅ |
String |
Rune |
✅ |
HashMap<K, V> |
(K, V) |
❌ |
HashSet<T> |
T |
❌ |
4. 迭代进阶
4.1 元组解构
- 对元素为元组的集合,可直接解构:
let points = [(1, 2), (3, 4), (5, 6)]
for ((x, y) in points) {
println("x=${x}, y=${y}")
}
- HashMap 迭代天然使用元组解构:
import std.collection.*
main() {
let map = HashMap<String, Int64>([("a", 1), ("b", 2)])
for ((key, value) in map) {
println("${key}: ${value}")
}
}
4.2 where 子句过滤
where在循环体执行前过滤,比循环体内if更简洁:
// ✅ 推荐:where 过滤
for (i in 0..20 where i % 3 == 0) {
println(i) // 0, 3, 6, 9, 12, 15, 18
}
// ❌ 不推荐:循环体内 if 判断
for (i in 0..20) {
if (i % 3 == 0) {
println(i)
}
}
4.3 break / continue
break提前退出循环,continue跳到下一次迭代- 二者类型均为
Nothing
for (i in 0..100) {
if (i > 5) { break }
if (i % 2 == 0) { continue }
println(i) // 1, 3, 5
}
4.4 String 迭代
注意 String 只实现了 Iterable<Byte>,逐字节而不是逐字符迭代:
for (ch in "Hi仓颉") {
println(ch) // 逐个输出:72 105 228 187 147 233 162 137
}
如果需要逐字符(Rune)迭代,可以先调用 toRuneArray() 转为字符数组后再使用:
for (ch in "Hi仓颉".toRuneArray()) {
println(ch) // 逐个输出:H i 仓 颉
}
5. 自定义可迭代类型
实现 Iterable<T> 接口即可获得 for-in 支持:
class Countdown <: Iterable<Int64> {
let start: Int64
init(start: Int64) { this.start = start }
public func iterator(): Iterator<Int64> {
CountdownIterator(start)
}
}
class CountdownIterator <: Iterator<Int64> {
var current: Int64
init(start: Int64) { current = start }
public func next(): Option<Int64> {
if (current > 0) {
let v = current
current--
return Some(v)
}
return None
}
}
main() {
for (i in Countdown(5)) {
print("${i} ") // 输出:5 4 3 2 1
}
}
6. 最优实践
6.1 优先使用 for-in
- for-in 比手动
while+iterator()更安全、简洁,且编译器可优化 - 需要索引时可结合
enumerate()(若集合支持),否则使用 Range:let arr = [10, 20, 30] for (i in 0..arr.size) { println("arr[${i}] = ${arr[i]}") }
6.2 Range 计数循环
- 固定次数循环优先用 Range,无需手动维护计数器:
// ✅ 推荐 for (_ in 0..n) { doSomething() } // ❌ 不推荐 var i = 0 while (i < n) { doSomething(); i++ }
6.3 where 替代 if
- 过滤场景优先用
where子句,减少嵌套、提升可读性(见 4.2)
6.4 注意无序集合
HashMap和HashSet迭代顺序不确定,不应依赖遍历顺序
6.5 常见错误
// ❌ 错误:试图修改迭代变量
for (i in 0..5) {
// i = i + 1 // 编译错误,迭代变量不可变
}
// ❌ 错误:step 为 0
// for (i in 0..10 : 0) { } // 运行时错误
// ❌ 错误:半开区间边界混淆
for (i in 0..5) { print(i) } // 01234,不包含 5
for (i in 0..=5) { print(i) } // 012345,包含 5
Weekly Installs
3
Repository
kong-baiming/cangjie-devFirst Seen
3 days ago
Security Audits
Installed on
opencode2
gemini-cli2
claude-code2
github-copilot2
codex2
kimi-cli2