我想在Crystal中实现Python的os.walk方法。我试图以递归方式进行操作,但是编译器告诉我要注意递归yielding,因为在编译时会无限递归生成代码。这就是我所写的:
def walk(d = @root, &block)
d = Dir.new(d) if d.is_a?(String)
dirs, files = d.entries.partition { |s| Dir.exists?(File.join(d.path, s)) }
if Dir.exists?(d.path)
yield d.path, dirs, files
dirs.each do |dir_name|
# recursively yield
walk File.join(d.path, dir_name), do |a, b, c|
yield a, b, c
end
end
end
end
Dir#each_child
而不是Dir#entries
,您无需过滤掉.
和..
。此外,在为该路径的条目创建迭代器后调用Dir.exists?
是不合逻辑的。 - Johannes MüllerDir#children
是Dir#entries
的替代品 - 谢谢!至于Dir#exists
,我不是在检查存在性,而是在检查路径是否为目录。如果有更好的方法,请告诉我,但是看看Dir#exists
的代码,它似乎只是一个围绕着 File.stat 的包装器,并检查它是否为目录。不知道如何以更便宜的方式检查路径是否为目录。 - mlobld.path
是否存在。如果不存在,Dir.new
已经会抛出异常了。 - Johannes Müller