You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Crystal中为递归树结构创建迭代器?

问题分析与代码修正

崩溃原因

你的代码触发TRAP (5)信号,核心问题是迭代器类型不匹配:
Iterator.chain要求所有参数必须是Iterator实例,但@children.each.flat_map(&.each_leaf)返回的是Enumerable(Int32)而非Iterator(Int32)。这种类型不匹配导致Crystal在隐式转换迭代器时出现内部逻辑错误,最终引发程序异常终止。

修正方案

方案1:修复迭代器构建逻辑

将flat_map替换为flat_map_iterator,这个方法会直接返回Iterator类型,符合Iterator.chain的参数要求:

# tree.cr
class Tree
  property children : Array(Tree)

  def initialize(@value : Int32)
    @children = [] of Tree
  end

  def add(child : Tree)
    @children << child
  end

  def each_leaf : Iterator(Int32)
    # 使用flat_map_iterator替代flat_map,确保返回Iterator类型
    Iterator.chain({@value}.each, @children.each.flat_map_iterator(&.each_leaf))
  end
end

root = Tree.new 3
root.add Tree.new 1
root.add Tree.new 5

p root.each_leaf.to_a # 输出 [3, 1, 5]
p "hi" # 输出 "hi"

方案2:如果需要真正的叶子节点(无后代的节点)

当前代码会遍历所有节点,若你实际需求是仅遍历叶子节点,需添加空节点判断:

def each_leaf : Iterator(Int32)
  if @children.empty?
    {@value}.each
  else
    @children.each.flat_map_iterator(&.each_leaf)
  end
end

此时调用root.each_leaf.to_a会输出[1, 5],因为节点3存在子节点,不属于叶子节点。

补充说明

Crystal中Enumerable和Iterator是不同的抽象,flat_map返回的是可枚举集合,而flat_map_iterator直接返回迭代器实例。错误的类型传递会导致迭代器嵌套逻辑混乱,触发未处理的底层信号。

内容的提问来源于stack exchange,提问作者Ding YuChen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 03:50:20