Jack Lee
Jack Lee

Reputation: 47

File.open('file.txt') vs. File.open('file.txt').readlines

I checked using File.open('file.txt').class and File.open('file.txt').readlines.class and the former one returns File and the latter returns Array.

I understand this difference, but if I do something like:

    File.open('file.txt').collect           {|l| l.upcase} 
=== File.open('file.txt').readlines.collect {|l| l.upcase}

it returns true. So are there any differences between the two objects when each item in the object is being passed to a block as an argument?

And also, I was assuming that the arguments that are passed to the block in both expressions are both a line in the file as a string which makes the comparison return true, is that correct? If so, how do I know what kind of argument will be passed to the block when I write the code? Do I have to check something like the documentation or the source code?

For example, I know how

['a','b','c'].each_with_index { |num, index|  puts "#{index + 1}: #{num}" }  

works and take this for granted. But how do I know the first argument should be each item in the array and the second the index, instead of the reverse?

Hope that makes sense, thanks!

Upvotes: 2

Views: 232

Answers (3)

steenslag
steenslag

Reputation: 80065

In Enumerable#each_with_index the arguments are in the same order as they are in the method name itself, first the element, then the index. Same thing with each_with_object.

Upvotes: 0

wurde
wurde

Reputation: 2617

Get comfortable doing some Ruby introspection in irb.

irb(main):001:0> puts File.ancestors.inspect
[File, IO, File::Constants, Enumerable, Object, Kernel, BasicObject]

This result shows us classes the File class inherits from and that includes the methods of class Enumerable. So what object is returned from File.readlines? An Array I think, let's check.

ri File.readlines
IO.readlines(name, sep=$/ [, open_args])     -> array
IO.readlines(name, limit [, open_args])      -> array
IO.readlines(name, sep, limit [, open_args]) -> array

This may be overkill, but we can verify Enumerable methods exists within an Array.

irb(main):003:0> puts Array.ancestors.inspect
[Array, Enumerable, Object, Kernel, BasicObject]

Upvotes: 1

djaszczurowski
djaszczurowski

Reputation: 4515

I'll try to make this response as compact as possible.

The second question - if you operate on objects which come from standard library you may always refer to their documentation in order to be 100% sure what arguments to expect when passing a block. For instance, multiple times you will be using methods like each, select, map (etc ...), on different data structures (Array, Hash, ...). Before you get used to them you may find all information about them in docs for example: http://ruby-doc.org/core-2.2.0/Array.html

If you are operating on non core data structures (for example a class which comes from gem you include, you should always browse it's documentation or sources on Github).

The first question. Result may be the same, when using different methods, but on deeper level there may be some differences. As far as your case is based on files. Reading file content may be processed in two ways. First - read everything into memory and operate on array of string, and the second - read file lines sequentially which may last longer but will not reserve as much memory.

Upvotes: 0

Related Questions