Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gets.chomp inside a function in ruby

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
like image 312
Sean Szurko Avatar asked Jan 09 '23 07:01

Sean Szurko


1 Answers

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.

like image 194
tilthouse Avatar answered Jan 19 '23 00:01

tilthouse