定义:
def trave_path path, *args
if File.directory? path
Dir.foreach(path) { |p| trave_path path + "/" + p, *args unless p =~ /^./ }
else
yield path, *args
end
end
调用('6124000'是目录,下面还包含目录,然后才是文件):
trave_path("61240000") do |pa|
p pa
end
报错:
D:/Program Files/Ruby1.86/Ruby/lib/lbc/Path.rb:6:in trave_path': no block give
trave_path'
(LocalJumpError)
from D:/Program Files/Ruby1.86/Ruby/lib/lbc/Path.rb:4:in
from D:/Program Files/Ruby1.86/Ruby/lib/lbc/Path.rb:4:in foreach'
trave_path'
from D:/Program Files/Ruby1.86/Ruby/lib/lbc/Path.rb:4:in
from D:/Program Files/Ruby1.86/Ruby/lib/lbc/Path.rb:4:in trave_path'
foreach'
from D:/Program Files/Ruby1.86/Ruby/lib/lbc/Path.rb:4:in
from D:/Program Files/Ruby1.86/Ruby/lib/lbc/Path.rb:4:in `trave_path'
from get_zfbp.rb:1
注意:如果“6124000”本身就是文件,程序是可以运行的。
难道不能在嵌套程序中调用block呢,还是我的用法不对。请大家指教。
哦另外,这个方法不是太安全。如果第一次调用传入的参数是一个不存在的路径,那么会进入else分支,而这并不意味着它是一个文件。不知道这个行为是否符合你原本的预期。我觉得还是用elsif File.file?来检查一下比较好
不是说“不能在嵌套程序中调用block”,而是你的写法使得递归调用中block没有被关联到方法上。就是说,这个调用:
[code="ruby"]trave_path path + "/" + p, *args[/code]
没有任何信息说明有block跟它关联着。Block与方法的关联关系在递归调用中是不继承的。
所以显式的指定这个关联关系就行:
[code="ruby"]def trave_path(path, *args, &b)
if File.directory? path
Dir.foreach(path) { |p| trave_path path + "/" + p, *args, &b unless p =~ /^./ }
else
b[path, *args]
end
end
#
trave_path('61240000') do |pa|
p pa
end[/code]
在给关联block名字之后,既可以照旧使用yield来调用关联block,也可以使用block的变量来调用。前面我是用了b[path, *args],这个是b.call(path, *args)的简写。
用回yield的话就是:
[code="ruby"]def trave_path(path, *args, &action)
if File.directory? path
Dir.foreach(path) { |p| trave_path path + "/" + p, *args, &action unless p =~ /^./ }
elsif File.file?
yield path, *args
end
end
trave_path('61240000') do |pa|
p pa
end[/code]