在Ruby中使用不同的闭包类型时奇怪的File.open行为

Dia*_*tis 7 ruby windows

我开始学习Chef来管理我们的服务器,我偶然发现了一个非常奇怪的(在我看来)Ruby中的行为.我不认识Ruby,所以这可能只是我的一个误解.

我得到的错误

`delete': Permission denied - [some path]/metadata.json (Errno::EACCES)
Run Code Online (Sandbox Code Playgroud)

因为我确定它实际上并不是关于权限,所以下一个合乎逻辑的事情是检查文件锁定.在通过相关代码挖掘了一下之后,我发现有一种方法可以为每个文件生成校验和.

def checksum_file(file, digest)
  File.open(file, 'rb') { |f| checksum_io(f, digest) }
end

def checksum_io(io, digest)
  while chunk = io.read(1024 * 8)
    digest.update(chunk)
  end
  digest.hexdigest
end
Run Code Online (Sandbox Code Playgroud)

找到了,我搜索了一下,找到了关于在Ruby中关闭文件的答案,看起来代码实际上很好......但事实并非如此.我试图将方法更改为"块格式",它没有错误地工作:

def checksum_file(file, digest)
  File.open(file, 'rb') do |f|
    checksum_io(f, digest)
  end
end
Run Code Online (Sandbox Code Playgroud)

有人可以解释两个版本的代码之间的区别吗?

- 编辑 -

似乎只有在Windows中才会出现此问题,并且可能仅在使用ChefDK 0.3.0提供的ruby时:

ruby 2.0.0p451(2014-02-24)[i386-mingw32]

VKa*_*atz 1

你的问题的答案

有人可以解释一下两个版本的代码之间的区别吗?

  • 块总是返回一些东西,所以do结束and并不{ ... }重要这只是人员编程偏好。

  • 我现在将向您分发两种不同的约定,具体取决于您想订阅哪种宗教。

第一个宗教说

当你有 a 时,single line or single line block你会使用大括号;如果你有 a ,multi line block你会使用doand end

words.each { |word| puts word }  # single line or single line block

words.each do |word|  # multi line block
  puts word
  p 1
end
Run Code Online (Sandbox Code Playgroud)

第二宗教说

如果你的块只是做了一些有副作用的事情,并且你不关心返回值,你可以放置 do 和 end

words.each do |word|
  puts word
end
Run Code Online (Sandbox Code Playgroud)

如果你确实关心返回值,你会使用 { ... }

back_words = words.map{ |word| word.reverse }
Run Code Online (Sandbox Code Playgroud)

希望我回答你的问题!