Richard Bucker

Ruby - ARGF interesting but destructive

Posted at — Jul 8, 2012

[Update 2012-07-08] I reviewed the ARGF source code and it explicitly closes the file. This is silly nonsense because (a) #close is supposed to perform a File::close and then advance to the next file in the list. (b) #close and #skip are not documented as aliases (c) the doc for #skip does not say anything about side effects.Thanks to the guys at pragprog I have been rereading pickaxe. And in the process I found the ARGF class. It seemed pretty interesting because it was supposed to process ARGV as if all of the arguments represented files. (state of the files not withstanding).The problem, however, is that it just feels improperly implemented. The first time you do anything with ARGF is has already opened the first file. And when you are on the last file where is no way to know other than checking closed? or fileno against the previous iteration. For example I would expect something like this:[sourcecode language=“ruby”]while ARGF.more?ARGF.skip# and then do some stuff to the fileend[/sourcecode]Instead you have to do this:[sourcecode language=“ruby”]while not ARGF.file.closed?# do some stuff to the fileARGF.skipend[/sourcecode]or the while loop could be:[sourcecode language=“ruby”]while ARGF.argv.size[/sourcecode]I suppose there is no much difference between the first example and the second from a structure perspective, however, there are side effects. Once you start to use ARGF the first file is opened. That might be a good thing and it might be bad. But it may also mean handling exceptions in more than one place. It certainly feels more verbose. Specially if you want to count the number of params by reusing ARGV.The big floppy issue, however, is that ARGF is destructive. ¬†Since ARGF connects to ARGV via a reference meaning that external code can alter the ARGV and the effects will be reflected in ARGF. The opposite is true too. ¬†When skip’ing over parameters ARGF appears to be removing the file from ARGV. Meaning that you cannot do anything with argv/ARGV after the fact as it has been consumed. (This side effect is never mentioned; in fact the documentation for ARGF never even hints at this.)The third piece of code makes processing easier but unexpected.