gets.chomp inside a function in ruby

1.9k Views Asked by At

I'm going through "Learn Ruby the Hard Way" and on exercise 20 there is a snippet of code that I don't understand. I don't understand why gets.chomp is called on f in the function "print_a_line".

input_file = ARGV.first

def print_all(f)
  puts f.read
end

def rewind(f)
  f.seek(0)
end

def print_a_line(line_count, f)
  puts "#{line_count}, #{f.gets.chomp}"
end

current_file = open(input_file)

puts "First let's print the whole file:\n"

print_all(current_file)

puts "Now let's rewind, kind of like a tape."

rewind(current_file)

puts "Let's print three lines:"

current_line = 1
print_a_line(current_line, current_file)

current_line = current_line + 1
print_a_line(current_line, current_file)

current_line = current_line + 1
print_a_line(current_line, current_file)

Consequently, I don't understand how the second part of the output is produced. I understand it is the first 3 lines of the test.txt file that is passed into the code, but I don't understand how f.gets.chomp produces this.

$ ruby ex20.rb test.txt
First let's print the whole file:
This is line 1
This is line 2
This is line 3
Now let's rewind, kind of like a tape.
Let's print three lines:
1, This is line 1
2, This is line 2
3, This is line 3
2

There are 2 best solutions below

0
On

If you take a look at the documentation for IO#gets, you'll see that it reads the next line from the IO object. The Kernel#open method you're calling will return the IO object that has that method. The #gets method is what is actually advancing you to the next line. It has nothing to do with #chomp on the string that it returned from reading the line.

1
On

The File object f keeps track (well, something it references keeps track) of where it is reading in the file. Think of this like a cursor that advances as you read in the file. When you tell f to gets, it reads until it hits the new line. They key is that f remembers where you are because the reading advanced the "cursor." The chomp call doesn't enter into this part at all. So every invocation of f.gets just reads the next line of the file and returns it as a string.

The chomp is only manipulating the string that is returned by f.gets and has no effect on the File object.

Edit: To complete the answer: chomp returns the string with the trailing newline removed. (Technically, it removes the record separator, but that is almost never different than newline.) This comes from Perl (AFAIK) and the idea is that basically you don't have to worry about if your particular form of getting input is passing you the newline characters or not.