Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Ruby let me call a String method without specifying the string?

Tags:

syntax

ruby

While reading Programming Ruby, I ran across this code snippet:

while gets
  num1, num2 = split /,/
end

While I intuitively understand what it does, I don't understand the syntax. 'split' is a method on the String class - in Ruby parlance, which string is the receiver of the 'split' message in the scenario above?

I can see in the docs that 'gets' assigns its result to the variable $_, so my guess is that it is implicitly using $_ as the receiver - but a whole bunch of Google searching has failed to confirm that guess. If that is the case, I'd love to know what general rule for methods called without an explicit receiver.

I did try the code in irb, with some diagnostic puts calls added, and I verified that the actual behavior is what you would expect - num1 and num2 get assigned values that were input separated by a comma.

like image 680
Bruce Avatar asked Nov 02 '11 20:11

Bruce


People also ask

What happens when you call a method in Ruby?

The Method class in Ruby has a source_location function that returns the location of the method's source code - file and line number where the method starts. Then method_source essentially opens that file, finds the respective line, looks for end that will end the method and returns the code in between.

How do you assign a string variable in Ruby?

Creating Strings: To create the string, just put the sequence of characters either in double quotes or single quotes. Also, the user can store the string into some variable. In Ruby, there is no need to specify the data type of the variable.

What does #{} mean in Ruby?

It is for String Interpolation.. In Ruby, there are three ways of interpolation, and #{} is just one way. apples = 4 puts "I have #{apples} apples" # or puts "I have %s apples" % apples # or puts "I have %{a} apples" % {a: apples}


2 Answers

Ruby 1.8 has a method Kernel#split([pattern [, limit]]) which is identical to $_.split(pattern, limit), and gets sets the value of $_.

like image 138
Michelle Tilley Avatar answered Oct 04 '22 22:10

Michelle Tilley


You basically nailed it with your explanation (at least for 1.8.7, 1.9.3 gave me a NoMethodError for main), but IMHO that's horrible Ruby (or maybe someone switching over from Perl). If you rewrite it to something like this, it becomes a lot clearer:

while input = gets.chomp
  num1, num2 = input.split(/,/)
end

The general rule for method calls without a receiver is that they are sent to self, whatever that may be in the current context. In the top level it's the aforementioned main, the $_ looping Perlism seems to be gone in 1.9.

like image 44
Michael Kohl Avatar answered Oct 05 '22 00:10

Michael Kohl