Eu vi muitas vezes em códigos Ruby File.open
chamadas incomparáveis
Você pode dar um exemplo? Eu só vejo isso em código escrito por iniciantes que não têm "conhecimento comum na maioria das linguagens de programação de que o fluxo para trabalhar com arquivos é abrir-usar-fechar".
Rubistas experientes fecham explicitamente seus arquivos ou, de forma mais linguística, usam a forma de bloco de File.open
, que fecha automaticamente o arquivo para você. Sua implementação é basicamente algo assim:
def File.open(*args, &block)
return open_with_block(*args, &block) if block_given?
open_without_block(*args)
end
def File.open_without_block(*args)
# do whatever ...
end
def File.open_with_block(*args)
yield f = open_without_block(*args)
ensure
f.close
end
Os scripts são um caso especial. Os scripts geralmente são executados tão curtos e usam tão poucos descritores de arquivo que simplesmente não faz sentido fechá-los, pois o sistema operacional os fechará de qualquer maneira quando o script for encerrado.
Precisamos fechar explicitamente?
Sim.
Se sim, por que o GC fecha automaticamente?
Porque depois de coletar o objeto, não há mais como você fechar o arquivo e, portanto, você vazaria os descritores de arquivo.
Observe que não é o coletor de lixo que fecha os arquivos. O coletor de lixo simplesmente executa quaisquer finalizadores para um objeto antes de coletá-lo. Acontece que a File
classe define um finalizador que fecha o arquivo.
Se não, por que a opção?
Porque a memória desperdiçada é barata, mas os descritores de arquivo desperdiçados não. Portanto, não faz sentido vincular o tempo de vida de um descritor de arquivo ao tempo de vida de algum pedaço de memória.
Você simplesmente não pode prever quando o coletor de lixo será executado. Você não pode sequer prever se ele será executado em tudo : se você nunca fique sem memória, o coletor de lixo nunca vai ficar, portanto, o finalizador nunca funcionará, portanto, o arquivo nunca será fechado.